目录
剑指 Offer 03. 数组中重复的数字
class Solution { public int findRepeatNumber(int[] nums) { Mapmap=new HashMap<>(); for (int i = 0; i if (!map.containsKey(nums[i])){ map.put(nums[i],1); }else { map.put(nums[i],map.get(nums[i])+1); } } for (Map.Entryentry:map.entrySet()) { if (entry.getValue()>1){ return entry.getKey(); } } return -1; } }
- 我的思路就是用一个hashmap来存储
- 一个注意点就是其map的遍历方式,用Entry的这种形式来遍历Map的元素
- 也可以用Set,因为其Set的唯一性,如果遇到了就直接返回这个指
剑指 Offer 04. 二维数组中的查找
class Solution { public boolean findNumberIn2DArray(int[][] matrix, int target) { if (matrix == null || matrix.length == 0 || matrix[0].length == 0) { return false; } int rows=0; int columns=matrix[0].length-1; if (target>matrix[matrix.length-1][columns]||target0][0]){ return false; }else { return helper(matrix,rows,columns,target);//从左上角开始递归 } } private boolean helper(int[][] matrix, int rows, int columns,int target) { if (rows<0||rows>matrix.length-1||columns<0||columns>matrix[0].length){ return false; } if (matrix[rows][columns]==target){ return true; }else if(matrix[rows][columns]>target){ return helper(matrix,rows,columns-1,target); }else { return helper(matrix,rows+1,columns,target); } } }
剑指 Offer 05. 替换空格
class Solution { public String replaceSpace(String s) { return s.replace(" ", "%20") ; } }
- 大概思路,创建一个新字符串,遇到空格就加%20,如果遇到别的字符,就直接添加
剑指 Offer 06. 从尾到头打印链表
栈的解法
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ class Solution { public int[] reversePrint(ListNode head) { LinkedListstack=new LinkedList<>(); while (head!=null){ stack.addLast(head.val); head=head.next; } int arr[]=new int[stack.size()]; for (int i = 0; i < arr.length; i++) { arr[i]=stack.removeLast(); } return arr; } }递归解法
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ class Solution { LinkedListlist=new LinkedList<>(); public int[] reversePrint(ListNode head) { helper(head); int arr[]=new int[list.size()]; for (int i = 0; i arr[i]=list.get(i); } return arr; } private void helper(ListNode head) { if (head==null) return; helper(head.next); list.add(head.val); } }
- 从这道题我们就可以目标,其实递归可以用栈实现,递归本质就是一个栈
剑指 Offer 07. 重建二叉树 LCOF
class Solution { public TreeNode buildTree(int[] preorder, int[] inorder) { int n=preorder.length-1; int m=inorder.length-1; return helper(preorder,0,n,inorder,0,m); //以pre[0,n]和ino[0,m]来创建树 pre[0]是根节点 ,通过ino来确定左右子树的范围 } private TreeNode helper(int[] preorder, int preStart, int n, int[] inorder, int inoStart, int m) { if(preStart>n){ //说明要构建的节点已经没有了 return null; } int rootVal=preorder[preStart];//要构造的根节点 int index=findNum(inorder,rootVal); int leftSize=index-inoStart; TreeNode root=new TreeNode(rootVal); root.left=helper(preorder,preStart+1,preStart+leftSize, inorder,inoStart,index-1); root.right=helper(preorder,preStart+leftSize+1,n, inorder,index+1,m); return root; } private int findNum(int[] inorder, int rootVal) { for (int i = 0; i < inorder.length; i++) { if (inorder[i]==rootVal){ return i; } } return -1; } }
剑指 Offer 09. 用两个栈实现队列
class CQueue { LinkedListA; LinkedListB; public CQueue() { A=new LinkedList<>(); B=new LinkedList<>(); //用B来存储数据,A来辅助 } public void appendTail(int value) { while (!B.isEmpty()){ int val=B.removeLast(); A.addLast(val); } A.addLast(value); while (!A.isEmpty()){ int val=A.removeLast(); B.addLast(val); } } public int deleteHead() { if (B.isEmpty()){ return -1; }else { return B.removeLast(); } } } /** * Your CQueue object will be instantiated and called as such: * CQueue obj = new CQueue(); * obj.appendTail(value); * int param_2 = obj.deleteHead(); */
剑指 Offer 11. 旋转数组的最小数字
class Solution { public int minArray(int[] numbers) { int right=numbers.length-1; int left=0; while (left int mid=left+(right-left)/2; if (numbers[mid]>numbers[right]){ left=mid+1; }else if(numbers[mid] right=mid; }else { //当两个值相同,不能判断这个值到底在左边还是在右边 //就将right-- //如果减去的这个值不是我们要找的,无所谓 //如果减去的值是我们要找的,那么数组中还是存在一个,不用担心 right--; } } return numbers[left]; } }
剑指 Offer 12. 矩阵中的路径
class Solution { public boolean exist(char[][] board, String word) { for (int i = 0; i < board.length; i++) { for (int j = 0; j < board[0].length; j++) { if (backtrack(board,i,j,word,0)){ return true; } } } return false; } /** * 表示从k到字符串结束,是否有字符串匹配 * @param board * @param i * @param j * @param word * @param k * @return */ private boolean backtrack(char[][] board, int i, int j, String word,int k ) { if (i<0||i>=board.length||j<0||j>=board[0].length||board[i][j]!=word.charAt(k)){ return false; //不满足条件 就不要再去往上下左右去走了 } if(k==word.length()-1){ //因为在前面这个判断,我们都会去判断响应的字符是否匹配上,如果都匹配上了k个字符,肯定就是可以的 return true; } board[i][j]='\0';//为什么这样做,这样就是相当于做选择,为什么,因为这样换,在下次肯定是匹配不上的 //这样也为了防止重复去利用了一个格子 走到这一步,也说明第k个的字符跟这个字符是匹配上的 //做出选择,让这个字符跟字符串中对应的字符去匹配 boolean res= backtrack(board,i+1,j,word,k+1)||backtrack(board,i,j+1,word,k+1)|| backtrack(board,i-1,j,word,k+1)||backtrack(board,i,j-1,word,k+1); board[i][j]=word.charAt(k); return res; } }
剑指 Offer 13. 机器人的运动范围
class Solution { boolean visited[][]; public int movingCount(int m, int n, int k) { this.visited = new boolean[m][n]; return backTrack(0,0,k,m,n); } private int backTrack(int row, int col, int k, int m, int n) { if (row<0||row>=m||col<0||col>=n||countNum(row,col)>k||visited[row][col]){ return 0; } //走到这里,说明这是一个还没有统计的格子 visited[row][col]=true; return 1+backTrack(row-1,col,k,m,n)+backTrack(row+1,col,k,m,n)+ backTrack(row,col-1,k,m,n)+backTrack(row,col+1,k,m,n); } public int countNum(int m,int n){ int sum=0; while (m>0){ sum+=m%10; m=m/10; } while (n>0){ sum+=n%10; n=n/10; } return sum; } }剑指 Offer 14- I. 剪绳子
public int cuttingRope(int n) { int dp[]=new int[n+1]; dp[1]=1; dp[2]=1; for (int i = 3; i <=n; i++) { for (int j = 2; j dp[i]= Math.max(dp[i],Math.max(j*(i-j),j*dp[i-j])); } } return dp[n]; }
剑指 Offer 15. 二进制中1的个数
正常思路
package Offer; public class offer15 { public int hammingWeight(int n) { int count=0; while (n!=0){ if ((n&1)==1){ count++; } n= n>>>1; } return count; } }n&(n-1)操作
- n-1相当将n的二进制最后一位的给消除(但是不能保证其他位的变为),n&(n-1)就是将除了将最后一位1变成0,其他不变
剑指 Offer 16. 数值的整数次方 快速幂问题
背后原理
二分实现
class Solution { public double myPow(double x, int n) { if (n==0){ return 1.0; } if(x==0){ return 0; } long n1=n; if (n<0){ x=1/x; n1=-n; } return helper(x, n1); } private double helper(double x, long n1) { if (n1==1){ return x; } if ((n1&1)==0){ //为偶数 return helper(x*x,n1>>>1); }else { return helper(x,n1-1)*x; } } }
剑指 Offer 17. 打印从1到最大的n位数
这道题,应该去考关于大数的处理
什么是大数
用回溯来完成所有的全排列
package Offer; import java.util.LinkedList; import java.util.List; public class Offer17 { //用于存储最终的结果 private Listlist=new LinkedList<>(); //用于存储每个符合要求的字符串 private StringBuilder track=new StringBuilder(); public void printNumbers(int n) { backtrack(n,0); System.out.println(list); } private void backtrack(int n, int cur) { if (cur==n){ //说明n位都有对应的数字了 list.add(track.toString()); return; } for (int i = 0; i <=n; i++) { //做选择 track.append(i); //进行下一个数字的选择 backtrack(n,cur+1); //回溯 track.deleteCharAt(track.length()-1); } } public static void main(String[] args) { Offer17 test=new Offer17(); test.printNumbers(5); } }
- 会出现这种高位为0的情况,如何避免呢?我们当track长度为0的时候,如果添加的数字是0,我们就跳过这次插入,这样就可以避免高位为0这种情况,比如我第一次要插入0,发现track为0,我们就插入第二位,发现track还是为0 ,也就会跳过
class Solution { //用于存储最终的结果 private Listlist=new LinkedList<>(); //用于存储每个符合要求的字符串 private StringBuilder track=new StringBuilder(); int []res; int count=0; public int[] printNumbers(int n) { res=new int[(int)(Math.pow(10,n)-1)]; backtrack(n,0); return res; } private void backtrack(int n, int cur) { if (cur==n){ //说明n位都有对应的数字了 if (track.length()!=0){ list.add(track.toString()); res[count]=Integer.parseInt(track.toString()); count++; } return; } for (int i = 0; i <=9; i++) { if (!(i==0&&track.length()==0)){ track.append(i); } //做选择 //进行下一个数字的选择 backtrack(n,cur+1); //回溯 if (!(i==0&&track.length()==0)){ track.deleteCharAt(track.length()-1); } } } }
剑指 Offer 18. 删除链表的节点
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ class Solution { public ListNode deleteNode(ListNode head, int val) { ListNode dummyHead=new ListNode(-1); dummyHead.next=head; ListNode prev=dummyHead; while (prev.next!=null){ ListNode node=prev.next; if (node.val==val){ prev.next=node.next; node=node.next=null; break; }else { prev=prev.next; } } return dummyHead.next; } }
- 这个题唯一的难点就是,删除头节点和非头节点的处理方式是一样的,这里我引入了虚拟头节点,就不用担心第一个是我们要删除的头节点,让虚拟头节点作为删除节点的前驱节点(删除节点最重要的就是要找到前驱节点)
- 相关阅读:
Linux 系统时间同步 使用 NTP 服务时间同步
Postman如何做接口测试6:如何使用外部 json 文件数据
Jackson自定义序列化
车牌自动识别-matlab
IAM、EIAM、CIAM、RAM、IDaaS 都是什么?
【PAT甲级】1127 ZigZagging on a Tree
编解码持续升级,「硬」实力铸就视频云最优解
C++ 使用栈求解中缀、后缀表达式的值
微信小程序| 打造ChatGPT英语四六级背单词小程序
dubbo入门小案例
- 原文地址:https://blog.csdn.net/qq_50985215/article/details/126092384