剑指offer
文章平均质量分 63
甄知一二
南七技校在读博
展开
-
剩余——11、29、31、33、41、42、45、46、63、64
11、二进制中1的个数要善用位运算若 n & 1 = 0n&1=0 ,则 nn 二进制 最右一位 为 00 ;若 n & 1 = 1n&1=1 ,则 nn 二进制 最右一位 为 11public class Solution { public int hammingWeight(int n) { int res = 0; while(n != 0) { res += n & 1;原创 2021-03-17 16:43:21 · 319 阅读 · 0 评论 -
递归数学——7、8、9、10、12、47、48
7、斐波那契数列递归是可以,但不如动态规划public class Solution { public int Fibonacci(int n) { if(n == 0) return 0; int[] dp = new int[n + 1]; dp[0] = 0; dp[1] = 1; for(int i = 2; i <= n; i++){ dp[i] = dp[i-1] + dp[原创 2021-03-13 16:42:49 · 279 阅读 · 0 评论 -
栈和队列——5、20、21
5、用两个栈实现队列解析import java.util.Stack;public class Solution { Stack<Integer> stack1 = new Stack<Integer>(); Stack<Integer> stack2 = new Stack<Integer>(); public void push(int node) { stack1.push(node);原创 2021-03-12 11:42:28 · 94 阅读 · 0 评论 -
回溯——65、66
65、矩阵中的路径解释很好首先,遍历整个矩阵,我们可以找到和字符串str首字符相同的单元格,作为查找的起点,然后遍历它的上下左右四个字符,如果有和str下一个字符相同的,就以该单元格作为下一个遍历起点,依次进行,如果没有找到就回退到上一个字符,重新查找其他方向。整个过程是一个非常典型的回溯思路。由于回溯法天生的递归特性,路径可以看做一个栈,当在矩阵中定位了路径中前n个字符的位置后,在第n个字符的上下左右(没有遍历过的)格子找第n+1个字符,如果没有找到,只能回退到第n-1个字符,重新定位第n个原创 2021-03-12 10:21:44 · 133 阅读 · 0 评论 -
树——23、24、26、68
前序遍历public TreeNode pruneTree (TreeNode root) { //前序 doSomeThing();root.left =pruneTree(root.left); root.right= pruneTree(root.right);}中序遍历public TreeNode pruneTree (TreeNode root) {root.left =pruneTree(root.left); //中序 doSomeThing(); root.原创 2021-03-11 17:29:28 · 139 阅读 · 0 评论 -
树——4、17、22、60、59、61
4、重建二叉树大佬的解析//利用原理,先序遍历的第一个节点就是根。在中序遍历中通过根 区分哪些是左子树的,哪些是右子树的 //左右子树,递归 HashMap<Integer, Integer> map = new HashMap<>();//标记中序遍历 int[] preorder;//保留的先序遍历 public TreeNode buildTree(int[] preorder, int[] inorder) { this.原创 2021-03-11 11:56:26 · 105 阅读 · 0 评论 -
树——18、38、39、57、58、62
18、二叉树的镜像索引root树的结点: root.left root.right解析不错class Solution { public TreeNode mirrorTree(TreeNode root) { if(root == null) return null; TreeNode tmp = root.left; root.left = mirrorTree(root.right); root.right = mi原创 2021-03-11 09:06:28 · 123 阅读 · 0 评论 -
链表——36、56、55、25
36、两个链表的第一个公共节点我们使用两个指针 node1,node2 分别指向两个链表 headA,headB 的头结点,然后同时分别逐结点遍历,当 node1 到达链表 headA 的末尾时,重新定位到链表 headB 的头结点;当 node2 到达链表 headB 的末尾时,重新定位到链表 headA 的头结点。这样,当它们相遇时,所指向的结点就是第一个公共结点。public class Solution { public ListNode getIntersectionNode原创 2021-03-08 15:43:03 · 125 阅读 · 0 评论 -
链表——3、14、15、16
3、从头到尾打印链表listNode 是链表,只能从头遍历到尾,但是输出却要求从尾到头,这是典型的"先进后出",我们可以想到栈!ArrayList 中有个方法是 add(index,value),可以指定 index 位置插入 value 值所以我们在遍历 listNode 的同时将每个遇到的值插入到 list 的 0 位置,最后输出 listNode 即可得到逆序链表Listnode list = new Listnode();那么list.val表示当前链表指针的值,list.next表示原创 2021-03-07 23:02:42 · 165 阅读 · 0 评论 -
字符串—43、44、49、52、53、54
43、左旋转字符串substring()的作用就是截取父字符串的某一部分public String substring(int beginIndex, int endIndex)第一个参数int为开始的索引,对应String数字中的开始位置,第二个参数是截止的索引位置,对应String中的结束位置1、取得的字符串长度为:endIndex - beginIndex;2、从beginIndex开始取,到endIndex结束,从0开始数,其中不包括endIndex位置的字符public class原创 2021-03-06 20:50:58 · 477 阅读 · 0 评论 -
字符串2、27、34
2、替换空格toCharArray() 字符数组javaimport java.util.*;public class Solution { public String replaceSpace (String s) { StringBuilder sb = new StringBuilder(); for(char c:s.toCharArray()){ sb.append(c==' '?"%20":c); }原创 2021-03-05 22:33:02 · 125 阅读 · 0 评论 -
数组—19、32、37、35
19、顺时针打印矩阵牛客的解法,还不错简单来说,就是不断地收缩矩阵的边界定义四个变量代表范围,up、down、left、right向右走存入整行的值,当存入后,该行再也不会被遍历,代表上边界的 up 加一,同时判断是否和代表下边界的 down 交错向下走存入整列的值,当存入后,该列再也不会被遍历,代表右边界的 right 减一,同时判断是否和代表左边界的 left 交错向左走存入整行的值,当存入后,该行再也不会被遍历,代表下边界的 down 减一,同时判断是否和代表上边界的 up 交错向原创 2021-03-04 16:54:23 · 216 阅读 · 1 评论 -
数组——50、1、13、40
50、数组中重复元素哈希表——set——遍历数组 o(n) o(n)class Solution { public int findRepeatNumber(int[] nums) { Set<Integer> set = new HashSet<Integer>(); int repeat = -1; for (int num : nums) { if (!set.add(num)) {原创 2021-03-03 22:58:21 · 219 阅读 · 0 评论 -
数组——6、28、30、51
6 、 旋转数组的最小数字这种二分查找难就难在,arr[mid]跟谁比.我们的目的是:当进行一次比较时,一定能够确定答案在mid的某一侧。一次比较为 arr[mid]跟谁比的问题。一般的比较原则有:如果有目标值target,那么直接让arr[mid] 和 target 比较即可。如果没有目标值,一般可以考虑 端点对于本题,非递减数组,选择右端点作为target比较好时间复杂度:二分,所以为O(logN), 但是如果是[1, 1, 1, 1],会退化到O(n)空间复杂度:没有开辟额外空间原创 2021-03-02 20:41:05 · 240 阅读 · 0 评论