Leetcode hot 100题目 easy部分 代码
1. 两数之和
暴力解法,通过两层放循环,实现查找。
20. 有效的括号
这道题的思路大概是 创建一个堆栈 用来保存匹配的左括号,一个hashMap ,map的的键值保成为左括号,map的值保存为右括号。 然后遍历 给定的字符串,当前元素如果是左括号,直接入栈。如果是右括号或?看该右括号是否能和遍历到中的字符匹配。首先将堆栈的最后一个元素出栈(左括号),获取该元素在map中对应的值(右括号),如果不等于当前遍历到的字符,返回错误。
最后只会剩余一个 '?',如果最后堆栈的大小为1,返回true
边界判断:如果stack是空,stack.pop()会有异常。所以在map中加入一对?的键值。
查看代码
class Solution { private static final Map<Character,Character> map = new HashMap<Character,Character>(){{ put('{','}'); put('[',']'); put('(',')'); put('?','?'); }}; public boolean isValid(String s) { if(s.length() > 0 && !map.containsKey(s.charAt(0))) return false; LinkedList<Character> stack = new LinkedList<Character>() {{ add('?'); }}; for(Character c : s.toCharArray()){ if(map.containsKey(c)) stack.addLast(c); else if(map.get(stack.removeLast()) != c) return false; } return stack.size() == 1; } } 作者:jyd 链接:https://leetcode-cn.com/problems/valid-parentheses/solution/valid-parentheses-fu-zhu-zhan-fa-by-jin407891080/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
同上
class Solution { public boolean isValid(String s) { //利用hashmap,堆栈,进行匹配,左括号入栈,否则出栈并和字符串元素对比 Stack stack = new Stack(); Map map = new HashMap(){{put('{','}');put('(',')');put('[',']');put('?','?');}}; stack.push('?');//考虑栈边界 for(Character c : s.toCharArray()){ if(map.containsKey(c)){ stack.push(c); }else if(!c.equals(map.get(stack.pop()))){ return false; } } return stack.size() == 1; } }
21. 合并两个有序链表
使用递归实现,如果L2的第一个元素小,将L2的next指针指向递归,如果L1的元素小较小,继续递归。
查看代码
class Solution { public ListNode mergeTwoLists(ListNode l1, ListNode l2) { if (l1 == null) { return l2; } else if (l2 == null) { return l1; } else if (l1.val < l2.val) { l1.next = mergeTwoLists(l1.next, l2); return l1; } else { l2.next = mergeTwoLists(l1, l2.next); return l2; } } } 作者:z1m 链接:https://leetcode-cn.com/problems/merge-two-sorted-lists/solution/yi-kan-jiu-hui-yi-xie-jiu-fei-xiang-jie-di-gui-by-/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
双指针迭代
class Solution { public ListNode mergeTwoLists(ListNode l1, ListNode l2) { ListNode dum = new ListNode(0), cur = dum; while(l1 != null && l2 != null) { if(l1.val < l2.val) { cur.next = l1; l1 = l1.next; } else { cur.next = l2; l2 = l2.next; } cur = cur.next; } cur.next = l1 != null ? l1 : l2; return dum.next; } } 作者:jyd 链接:https://leetcode.cn/problems/he-bing-liang-ge-pai-xu-de-lian-biao-lcof/solution/mian-shi-ti-25-he-bing-liang-ge-pai-xu-de-lian-b-2/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
53. 最大子数组和
使用贪心算法,时间复杂度o(n),空间复杂度o(1)。
定义一个最小和sum,一个max记录每次数组边化之后的和,两个指针left和right。
零下标开始,从左到右 开始记录max的值。将右指针元素加入到max中,再比较相加之后的max和右指针元素,如果相加之后的max值更小,则要将max去掉左指针的元素,左指针开始右移,直到移动到右指针处。得到最大值之后,最大值和之前求得的sum进行比较取较大的。完成一次比较后将右指针右移。
查看代码
class Solution { public int maxSubArray(int[] nums) { int left = 0,right = 0; int max = 0; int sum = Integer.MIN_VALUE; while(right < nums.length){ max += nums[right]; while(max - nums[right] < 0 && left <= right){ max -= nums[left]; left ++; } sum = Math.max(max,sum); right ++; } return sum; } } 作者:xjszsd 链接:https://leetcode-cn.com/problems/maximum-subarray/solution/by-gu-shi-zhong-you-jie-9r24/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
动态规划解法:
讲解看LeetCode,讲解非常清晰。
动态规划未优化
public class Solution { public int maxSubArray(int[] nums) { int pre = 0; int res = nums[0]; for (int num : nums) { pre = Math.max(pre + num, num); res = Math.max(res, pre); } return res; } } 作者:liweiwei1419 链接:https://leetcode.cn/problems/maximum-subarray/solution/dong-tai-gui-hua-fen-zhi-fa-python-dai-ma-java-dai/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
动态规划优化版本
from typing import List class Solution: def maxSubArray(self, nums: List[int]) -> int: size = len(nums) pre = 0 res = nums[0] for i in range(size): pre = max(nums[i], pre + nums[i]) res = max(res, pre) return res 作者:liweiwei1419 链接:https://leetcode.cn/problems/maximum-subarray/solution/dong-tai-gui-hua-fen-zhi-fa-python-dai-ma-java-dai/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
70. 爬楼梯
1,使用普通递归方法。(答案超时)
2,进一步化简,可以使用记忆化递归方法,即用数组记录第n阶台阶的值。
3,动态规划,记录n个状态,从1到n依次更新
4,斐波那契数列
5,用现代知识
普通递归(超时)
class Solution { public int climbStairs(int n) { if(n == 1){ return 1; } if( n == 2 ) return 2; return climbStairs(n - 1) + climbStairs(n -2); } }
以上方法会重复递归。
使用记忆化递归,用一个memo数组存储递归过的结果。时间空间复杂度可以到O(n)
记忆化的递归
class Solution { public int climbStairs(int n) { int memo[] = new int[n + 1]; return climbStairsMemo(n,memo); } //构造数组 public int climbStairsMemo(int n,int memo[]){ if(memo[n] > 0) return memo[n]; if(n == 1){ memo[n] = 1; }else if(n == 2){ memo[n] = 2; }else{ memo[n] = climbStairsMemo(n-1,memo) + climbStairsMemo(n-2,memo); } return memo[n]; } }
94. 二叉树的中序遍历
1,使用递归解法
2,迭代方法,定义一个堆栈
递归做法
class Solution { public List<Integer> inorderTraversal(TreeNode root) { List<Integer> res = new ArrayList<Integer>(); inorder(root, res); return res; } public void inorder(TreeNode root, List<Integer> res) { if (root == null) { return; } inorder(root.left, res); res.add(root.val); inorder(root.right, res); } } 作者:LeetCode-Solution 链接:https://leetcode-cn.com/problems/binary-tree-inorder-traversal/solution/er-cha-shu-de-zhong-xu-bian-li-by-leetcode-solutio/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
迭代实现
class Solution { public List<Integer> inorderTraversal(TreeNode root) { List<Integer> res = new ArrayList<Integer>(); Deque<TreeNode> stk = new LinkedList<TreeNode>(); while (root != null || !stk.isEmpty()) { while (root != null) { stk.push(root); root = root.left; } root = stk.pop(); res.add(root.val); root = root.right; } return res; } } 作者:LeetCode-Solution 链接:https://leetcode-cn.com/problems/binary-tree-inorder-traversal/solution/er-cha-shu-de-zhong-xu-bian-li-by-leetcode-solutio/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
101. 对称二叉树
递归判断,判断A,B两指针节点是否相等,A的右子树与B的左子树是否对称相等,判断A的左子树与B的右子树是否对称相等。
注意递归重点的顺序:先判断左右结点,都为空返回true,然后如果两者中的一个为空,返回false,用`||`符号,最后的情况是两者都不为空的情况。
递归判断对称
class Solution { public boolean isSymmetric(TreeNode root) { if(root==null) { return true; } //调用递归函数,比较左节点,右节点 return dfs(root.left,root.right); } boolean dfs(TreeNode left, TreeNode right) { //递归的终止条件是两个节点都为空 //或者两个节点中有一个为空 //或者两个节点的值不相等 if(left==null && right==null) { return true; } if(left==null || right==null) { return false; } if(left.val!=right.val) { return false; } //再递归的比较 左节点的左孩子 和 右节点的右孩子 //以及比较 左节点的右孩子 和 右节点的左孩子 return dfs(left.left,right.right) && dfs(left.right,right.left); } } 作者:wang_ni_ma 链接:https://leetcode-cn.com/problems/symmetric-tree/solution/dong-hua-yan-shi-101-dui-cheng-er-cha-shu-by-user7/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
104. 二叉树的最大深度
递归做法。节点为空时说明高度为 0,所以返回 0;节点不为空时则分别求左右子树的高度的最大值,同时加1表示当前节点的高度
查看代码
/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ class Solution { public int maxDepth(TreeNode root) { if(root == null) { return 0; } else { int left = maxDepth(root.left); int right = maxDepth(root.right); return Math.max(left, right) + 1; } } } 作者:guanpengchn 链接:https://leetcode-cn.com/problems/maximum-depth-of-binary-tree/solution/hua-jie-suan-fa-104-er-cha-shu-de-zui-da-shen-du-b/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
121. 买卖股票的最佳时机
暴力解法思路:枚举所有发生一次交易的股价差。
暴力解法(运行超时)
public class Solution { public int maxProfit(int[] prices) { int len = prices.length; if (len < 2) { return 0; } // 有可能不发生交易,因此结果集的初始值设置为 0 int res = 0; // 枚举所有发生一次交易的股价差 for (int i = 0; i < len - 1; i++) { for (int j = i + 1; j < len; j++) { res = Math.max(res, prices[j] - prices[i]); } } return res; } } 作者:liweiwei1419 链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/solution/bao-li-mei-ju-dong-tai-gui-hua-chai-fen-si-xiang-b/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
动态规划没咋看懂
public class Solution { public int maxProfit(int[] prices) { int len = prices.length; // 特殊判断 if (len < 2) { return 0; } int[][] dp = new int[len][2]; // dp[i][0] 下标为 i 这天结束的时候,不持股,手上拥有的现金数 // dp[i][1] 下标为 i 这天结束的时候,持股,手上拥有的现金数 // 初始化:不持股显然为 0,持股就需要减去第 1 天(下标为 0)的股价 dp[0][0] = 0; dp[0][1] = -prices[0]; // 从第 2 天开始遍历 for (int i = 1; i < len; i++) { dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] + prices[i]); dp[i][1] = Math.max(dp[i - 1][1], -prices[i]); } return dp[len - 1][0]; } } 作者:liweiwei1419 链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/solution/bao-li-mei-ju-dong-tai-gui-hua-chai-fen-si-xiang-b/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
一次遍历
public class Solution { public int maxProfit(int prices[]) { int minprice = Integer.MAX_VALUE; int maxprofit = 0; for (int i = 0; i < prices.length; i++) { if (prices[i] < minprice) { minprice = prices[i]; } else if (prices[i] - minprice > maxprofit) { maxprofit = prices[i] - minprice; } } return maxprofit; } } 作者:LeetCode-Solution 链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/solution/121-mai-mai-gu-piao-de-zui-jia-shi-ji-by-leetcode-/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
使用minprice获得最小股价,使用maxprofit记录最大收益
迭代,当前股价小于最小股价,说明下跌了,更新最小股价。如果当前股价减去最小价格大于最大收益,则更新maxprofit的值。一直迭代得到最大收益。
136. 只出现一次的数字
如果允许使用额外空间,可以使用哈希表或集合。
要求不使用额外的空间,可以使用异或运算符号解决问题:
异或运算符解法代码实现
class Solution { public int singleNumber(int[] nums) { int single = 0; for (int num : nums) { single ^= num; } return single; } } 作者:LeetCode-Solution 链接:https://leetcode-cn.com/problems/single-number/solution/zhi-chu-xian-yi-ci-de-shu-zi-by-leetcode-solution/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
141. 环形链表
思路:使用快慢指针,快指针每次走两步,慢指针每次走一步。如果有环,快慢指针会相遇。
快慢指针做法
/** * Definition for singly-linked list. * class ListNode { * int val; * ListNode next; * ListNode(int x) { * val = x; * next = null; * } * } */ public class Solution { public boolean hasCycle(ListNode head) { //快慢指针 ListNode slow = head,fast = head; while(slow!=null&&fast.next!=null&&fast.next.next!=null){ //慢指针走一步,快指针走两步 slow = slow.next; fast = fast.next.next; //当快慢指针相遇的时候,则链表存在环 if(slow == fast){ return true; } } return false; } }
链表问题:https://leetcode-cn.com/problems/linked-list-cycle/solution/yi-wen-gao-ding-chang-jian-de-lian-biao-wen-ti-h-2/
155. 最小栈
使用辅助栈保存当前数据栈中的最小元素。进栈时数据栈直接入栈,如果入栈元素大于辅助栈栈顶元素,再将辅助栈顶元素入辅助栈,如果入栈元素小于辅助栈栈顶元素,将入栈元素入辅助栈。出栈时,两个栈同时出栈。
stack.peek():该方法返回堆栈顶部的元素,如果堆栈为空,则返回NULL
辅助栈解法
import java.util.Stack; public class MinStack { // 数据栈 private Stack<Integer> data; // 辅助栈 private Stack<Integer> helper; /** * initialize your data structure here. */ public MinStack() { data = new Stack<>(); helper = new Stack<>(); } // 思路 1:数据栈和辅助栈在任何时候都同步 public void push(int x) { // 数据栈和辅助栈一定会增加元素 data.add(x); if (helper.isEmpty() || helper.peek() >= x) { helper.add(x); } else { helper.add(helper.peek()); } } public void pop() { // 两个栈都得 pop if (!data.isEmpty()) { helper.pop(); data.pop(); } } public int top() { if(!data.isEmpty()){ return data.peek(); } throw new RuntimeException("栈中元素为空,此操作非法"); } public int getMin() { if(!helper.isEmpty()){ return helper.peek(); } throw new RuntimeException("栈中元素为空,此操作非法"); } } 作者:liweiwei1419 链接:https://leetcode-cn.com/problems/min-stack/solution/shi-yong-fu-zhu-zhan-tong-bu-he-bu-tong-bu-python-/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
160. 相交链表
这题也是计算机综合考试考研题目真题。
双指针思路:
pA走过的路径为A链+B链
pB走过的路径为B链+A链
pA和pB走过的长度都相同,都是A链和B链的长度之和,相当于将两条链从尾端对齐,如果相交,则会提前在相交点相遇,如果没有相交点,则会在最后相遇。
pA:1->2->3->4->5->6->null->9->5->6->null pB:9->5->6->null->1->2->3->4->5->6->null
也可理解为:
若相交,链表A: a+c, 链表B : b+c ,a+c+b+c = b+c+a+c 则会在公共处c起点相遇。
若不相交,a +b = b+a 。因此相遇处是NULL
双指针题解
public ListNode getIntersectionNode(ListNode headA, ListNode headB) { if (headA == null || headB == null) return null; ListNode pA = headA, pB = headB; while (pA != pB) { pA = pA == null ? headB : pA.next; pB = pB == null ? headA : pB.next; } return pA; } 作者:reals 链接:https://leetcode-cn.com/problems/intersection-of-two-linked-lists/solution/tu-jie-xiang-jiao-lian-biao-by-user7208t/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
169. 多数元素
排序
class Solution { public int majorityElement(int[] nums) { Arrays.sort(nums); return nums[nums.length >> 1]; } }
摩尔投票法:B站视频讲解
摩尔投票法
class Solution { public int majorityElement(int[] nums) { int cand_num = nums[0], count = 1; for (int i = 1; i < nums.length; ++i) { if (cand_num == nums[i]) ++count; else if (--count == 0) { cand_num = nums[i]; count = 1; } } return cand_num; } } 作者:gfu 链接:https://leetcode-cn.com/problems/majority-element/solution/3chong-fang-fa-by-gfu-2/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
206. 反转链表
双指针算法:
双指针
class Solution { public ListNode reverseList(ListNode head) { ListNode prev = null; ListNode curr = head; while (curr != null) { ListNode next = curr.next; curr.next = prev; prev = curr; curr = next; } return prev; } } 作者:LeetCode-Solution 链接:https://leetcode.cn/problems/reverse-linked-list/solution/fan-zhuan-lian-biao-by-leetcode-solution-d1k2/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
递归做法:
递归做法: 递归动画演示
查看代码
class Solution { public ListNode reverseList(ListNode head) { //递归终止条件是当前为空,或者下一个节点为空 if(head==null || head.next==null) { return head; } //这里的cur就是最后一个节点 ListNode cur = reverseList(head.next); //这里请配合动画演示理解 //如果链表是 1->2->3->4->5,那么此时的cur就是5 //而head是4,head的下一个是5,下下一个是空 //所以head.next.next 就是5->4 head.next.next = head; //防止链表循环,需要将head.next设置为空 head.next = null; //每层递归函数都返回cur,也就是最后一个节点 return cur; } } 作者:wang_ni_ma 链接:https://leetcode-cn.com/problems/reverse-linked-list/solution/dong-hua-yan-shi-206-fan-zhuan-lian-biao-by-user74/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
226. 翻转二叉树
递归做法
class Solution { public TreeNode invertTree(TreeNode root) { //递归函数的终止条件,节点为空时返回 if(root==null) { return null; } //下面三句是将当前节点的左右子树交换 TreeNode tmp = root.right; root.right = root.left; root.left = tmp; //递归交换当前节点的 左子树 invertTree(root.left); //递归交换当前节点的 右子树 invertTree(root.right); //函数返回时就表示当前这个节点,以及它的左右子树 //都已经交换完了 return root; } } 作者:wang_ni_ma 链接:https://leetcode-cn.com/problems/invert-binary-tree/solution/dong-hua-yan-shi-liang-chong-shi-xian-226-fan-zhua/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
也可以用层序遍历的方法,利用辅助队列做。
修改 node 会影响root的内存,其中因为最开始 node和 root 都是引用同一个对象的,类似于c++的指针。不直接操作root,是为了防止丢失root指针。
层序遍历
class Solution { public TreeNode mirrorTree(TreeNode root) { if(root == null) return null; Queue<TreeNode> queue = new LinkedList(){{offer(root);}}; while(!queue.isEmpty()){ TreeNode node = queue.poll(); TreeNode tmp = node.left; node.left = node.right; node.right = tmp; if(node.left != null) queue.offer(node.left); if(node.right != null) queue.offer(node.right); } return root; } } 作者:wang_ni_ma 链接:https://leetcode-cn.com/problems/invert-binary-tree/solution/dong-hua-yan-shi-liang-chong-shi-xian-226-fan-zhua/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
234. 回文链表
复制到数组中再用双指针:
class Solution { public boolean isPalindrome(ListNode head) { List<Integer> vals = new ArrayList<Integer>(); // 将链表的值复制到数组中 ListNode currentNode = head; while (currentNode != null) { vals.add(currentNode.val); currentNode = currentNode.next; } // 使用双指针判断是否回文 int front = 0; int back = vals.size() - 1; while (front < back) { if (!vals.get(front).equals(vals.get(back))) { return false; } front++; back--; } return true; } } 作者:LeetCode-Solution 链接:https://leetcode-cn.com/problems/palindrome-linked-list/solution/hui-wen-lian-biao-by-leetcode-solution/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
快慢指针做法:整个流程可以分为以下五个步骤:
找到前半部分链表的尾节点。
反转后半部分链表。
判断是否回文。
恢复链表。
返回结果
class Solution { public boolean isPalindrome(ListNode head) { if (head == null) { return true; } // 找到前半部分链表的尾节点并反转后半部分链表 ListNode firstHalfEnd = endOfFirstHalf(head); ListNode secondHalfStart = reverseList(firstHalfEnd.next); // 判断是否回文 ListNode p1 = head; ListNode p2 = secondHalfStart; boolean result = true; while (result && p2 != null) { if (p1.val != p2.val) { result = false; } p1 = p1.next; p2 = p2.next; } // 还原链表并返回结果 firstHalfEnd.next = reverseList(secondHalfStart); return result; } private ListNode reverseList(ListNode head) { ListNode prev = null; ListNode curr = head; while (curr != null) { ListNode nextTemp = curr.next; curr.next = prev; prev = curr; curr = nextTemp; } return prev; } private ListNode endOfFirstHalf(ListNode head) { ListNode fast = head; ListNode slow = head; while (fast.next != null && fast.next.next != null) { fast = fast.next.next; slow = slow.next; } return slow; } } 作者:LeetCode-Solution 链接:https://leetcode-cn.com/problems/palindrome-linked-list/solution/hui-wen-lian-biao-by-leetcode-solution/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
338. 比特位计数
Brian Kernighan 算法的原理:对于任意整数 x,令 x=x & (x−1),该运算将 x 的二进制表示的最后一个 1 变成 0。因此,对 x 重复该操作,直到 x 变成 0,则操作次数即为 x 的「一比特数」。
例如:5的二进制表示是101,操作两次101 & 100 -》100 & 011-》0
用brian kernighan 算法
class Solution { public int[] countBits(int n) { int[] bits = new int[n + 1]; for (int i = 0; i <= n; i++) { bits[i] = countOnes(i); } return bits; } public int countOnes(int x) { int ones = 0; while (x > 0) { x &= (x - 1); ones++; } return ones; } } 作者:LeetCode-Solution 链接:https://leetcode-cn.com/problems/counting-bits/solution/bi-te-wei-ji-shu-by-leetcode-solution-0t1i/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
还有更巧妙的做法:
二进制表示中,奇数一定比前面那个偶数多一个 1。偶数中 1 的个数一定和除以 2 之后的那个数一样多。
奇数举例: 0 = 0 1 = 1 2 = 10 3 = 11 偶数举例: 2 = 10 4 = 100 8 = 1000 3 = 11 6 = 110 12 = 1100
查看代码
vector<int> countBits(int num) { vector<int> result(num+1); result[0] = 0; for(int i = 1; i <= num; i++) { if(i % 2 == 1) { result[i] = result[i-1] + 1; } else { result[i] = result[i/2]; } } return result; } 作者:duadua 链接:https://leetcode-cn.com/problems/counting-bits/solution/hen-qing-xi-de-si-lu-by-duadua/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
283. 移动零
思路:创建两个指针i和j,第一次遍历的时候,i从0下标开始遍历到数组末尾,每遇到一个非0元素就将i下标所在元素赋值给指针j所在下标,第一次遍历完后,j指针的下标就指向了最后一个非0元素下标。第二次遍历的时候,起始位置就从j开始到结束,将剩下的这段区域内的元素全部置为0。
两次遍历
class Solution { public void moveZeroes(int[] nums) { if(nums==null) { return; } //第一次遍历的时候,j指针记录非0的个数,只要是非0的统统都赋给nums[j] int j = 0; for(int i=0;i<nums.length;++i) { if(nums[i]!=0) { nums[j++] = nums[i]; } } //非0元素统计完了,剩下的都是0了 //所以第二次遍历把末尾的元素都赋为0即可 for(int i=j;i<nums.length;++i) { nums[i] = 0; } } } 作者:wang_ni_ma 链接:https://leetcode-cn.com/problems/move-zeroes/solution/dong-hua-yan-shi-283yi-dong-ling-by-wang_ni_ma/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
448. 找到所有数组中消失的数字
原地哈希:
从0下标开始遍历,如果下标所在元素等于下标+1,说明这个元素在它的位置,索引自增遍历就行。如果不等,先求出当前元素的目标索引targetIndex:元素值-1,如果目标索引的元素值等于当前索引的值,说明元素重复,索引自增,并跳过此次循环。如果不重复,交换两个元素。
最后遍历数组,如果元素值不等于索引+1,说明 索引+1 缺失。
原地哈希
class Solution { public List<Integer> findDisappearedNumbers(int[] nums) { int len = nums.length; int index = 0; while(index < len){ if(nums[index] == index + 1){ index++; }else{ int targetIndex = nums[index] - 1; if(nums[targetIndex] == nums[index]){ index++; continue; } int temp = nums[targetIndex]; nums[targetIndex] = nums[index]; nums[index] = temp; } } List<Integer> res = new ArrayList<>(); for(int i = 0; i < len; i++){ if(nums[i] != i + 1) res.add(i + 1); } return res; } } 作者:venturekwok 链接:https://leetcode-cn.com/problems/find-all-numbers-disappeared-in-an-array/solution/java-yuan-di-ha-xi-si-lu-qing-xi-dai-ma-a12yd/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
461. 汉明距离
在工程中,我们应该直接使用内置函数
直接调用函数
class Solution { public int hammingDistance(int x, int y) { return Integer.bitCount(x ^ y); } } 作者:LeetCode-Solution 链接:https://leetcode-cn.com/problems/hamming-distance/solution/yi-ming-ju-chi-by-leetcode-solution-u1w7/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
也可以自己手动检测1的位数
查看代码
//如果最低位为 1,那么令计数器加一,然后我们令 s 整体右移一位。这样 s 的最低位将被舍去,原本的次低位就变成了新的最低位。 //我们重复这个过程直到 s=0 为止。 class Solution { public int hammingDistance(int x, int y) { int s = x ^ y, ret = 0; while (s != 0) { ret += s & 1; s >>= 1; } return ret; } } 作者:LeetCode-Solution 链接:https://leetcode-cn.com/problems/hamming-distance/solution/yi-ming-ju-chi-by-leetcode-solution-u1w7/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
543. 二叉树的直径
思路:根节点可能不在直径上面,任意节点开始计算。重点是任意一个结点,都要记录以此结点为根的直径情况:左子树高度+右子树高度
预防踩坑:leetcode
查看代码
class Solution { private int ans;//需要一个值来保存每次比较更新的最大直径值 public int diameterOfBinaryTree(TreeNode root) { if(root == null){ return -1; } maxDepth(root); return ans; } private int maxDepth(TreeNode root) { if(root == null){ return 0; } int left = maxDepth(root.left); int right = maxDepth(root.right); ans = Math.max(ans, left + right); return Math.max(left, right) + 1; } }
617. 合并二叉树
递归实现合并,如果两个二叉树中的的某个二叉树节点为空,返回不为空的节点。将第二个二叉树节点合并到第一个二叉树节点上面。最后返回第一颗二叉树。
递归实现
class Solution { public TreeNode mergeTrees(TreeNode t1, TreeNode t2) { if(t1==null || t2==null) { return t1==null? t2 : t1; } return dfs(t1,t2); } TreeNode dfs(TreeNode r1, TreeNode r2) { // 如果 r1和r2中,只要有一个是null,函数就直接返回 if(r1==null || r2==null) { return r1==null? r2 : r1; } //让r1的值 等于 r1和r2的值累加,再递归的计算两颗树的左节点、右节点 r1.val += r2.val; r1.left = dfs(r1.left,r2.left); r1.right = dfs(r1.right,r2.right); return r1; } } 作者:wang_ni_ma 链接:https://leetcode-cn.com/problems/merge-two-binary-trees/solution/dong-hua-yan-shi-di-gui-die-dai-617he-bing-er-cha-/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
posted on 2022-05-07 21:47 passionConstant 阅读(27) 评论(0) 编辑 收藏 举报
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效