Leetcode 编程能力入门徽章最佳实践 基本数据类型 1523. 在区间范围内统计奇数数目 思路一:
[low, high]上循环遍历
判断是不是奇数 <=> 是否能被2整除
返回函数为int,全局累加
1 2 3 4 5 6 7 8 9 class Solution { public int countOdds (int low, int high) { int ans = 0 ; for (int i = low; i <=high; i++ ){ if (i % 2 != 0 ) ans++; } return ans; } }
但是超时了。。。时间复杂度O(n) 所以我们需要判断如何准确用公式总结问题的规律,[3, 7]有三个奇数,
1 2 3 4 5 class Solution { public int countOdds (int low, int high) { return (high+1 >> 1 ) - (low >> 1 ); } }
1491. 去掉最低工资和最高工资后的工资平均值 思路一:
Arrays内置排序+遍历的方法
确定边界,排序后的第二个元素到倒数第二个
sum为double类型,自动向上转型
1 2 3 4 5 6 7 8 9 10 11 12 class Solution { public double average (int [] salary) { int length = salary.length; int n = length - 2 ; double sum = 0 ; Arrays.sort(salary); for (int i = 1 ; i <= n; i++) { sum += salary[i]; } return sum/n; } }
但是排序对于空间复杂度要求较高,只击败了5%的用户 思路二:
用整数默认最大值初始化全局最小值,整数默认最小值初始化全局最大值,设置全局累加值sum
遍历的过程中更新最小值和最大值
用公式(sum-min-max)/(length-2)返回结果
1 2 3 4 5 6 7 8 9 10 11 12 class Solution { public double average (int [] salary) { double sum = 0 ; double maxValue = Integer.MIN_VALUE, minValue = Integer.MAX_VALUE; for (int num : salary) { sum += num; maxValue = Math.max(maxValue, num); minValue = Math.min(minValue, num); } return (sum - maxValue - minValue) / (salary.length - 2 ); } }
运算符 191. 位1的个数 思路:
int默认是有符号数,因此无法用取余进行操作,需要用按位与进行判别当前位是不是1,如果是结果就加上1,否则加0
每次右移1位
1 2 3 4 5 6 7 8 9 10 11 public class Solution { public int hammingWeight (int n) { int ans = 0 ; for (int i = 1 ; i <= 32 ; i++){ ans += n&1 ; n >>= 1 ; } return ans; } }
1281. 整数的各位积和之差 思路:
取得十进制数每位上的数字(从后往前取)
算得累积, 和累加和
返回积与和的差值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class Solution { public int subtractProductAndSum (int n) { int area = 1 ; int sum = 0 ; while (n>0 ){ int p = n%10 ; area *= p; sum += p; n /= 10 ; } return area-sum; } }
条件语句 976. 三角形的最大周长 思路:
排好序从后往前找
如果能构成三角形,则返回周长
否则往前移一位
如果检索到开头,没有能构成三角形的,则返回0
1 2 3 4 5 6 7 8 9 10 11 class Solution { public int largestPerimeter (int [] A) { Arrays.sort(A); for (int i = A.length - 1 ; i >= 2 ; --i) { if (A[i - 2 ] + A[i - 1 ] > A[i]) { return A[i - 2 ] + A[i - 1 ] + A[i]; } } return 0 ; } }
1779. 找到最近的有相同 X 或 Y 坐标的点 思路:
需要两个确据变量最短曼哈顿距离的数组下标和最短曼哈顿距离
遍历二维数组
判断是不是有效点
判断有效点的曼哈顿距离是否小于当前最短曼哈顿距离,如果是的话更新最短曼哈顿距离的数组下标和最短曼哈顿距离
最终遍历完返回最短曼哈顿距离的数组下标
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class Solution { public int nearestValidPoint (int x, int y, int [][] points) { int minIndex = -1 ; int minJuLi = Integer.MAX_VALUE; for (int i=0 ;i<points.length;i++){ if (x==points[i][0 ]||y==points[i][1 ]){ int res = Math.abs(x-points[i][0 ])+Math.abs(y-points[i][1 ]); if (res<minJuLi){ minJuLi = res; minIndex = i; } } } return minIndex; } }
循环 思路:
用异或进行进行取反,目的是为了保留符号位,同号得正(0),异号得负(1)
1 2 3 4 5 6 7 8 9 10 11 12 class Solution { public int arraySign (int [] nums) { int ans = 0 ; for (int i : nums) { if (i == 0 ) return 0 ; ans ^= i; } return ans >= 0 ? 1 : -1 ; } }
1 2 3 4 5 6 7 8 9 10 11 12 class Solution { public int arraySign (int [] nums) { int res = 1 ; for (int i : nums) { if (i == 0 ) return 0 ; if (i < 0 ) res *= -1 ; if (i> 0 ) res *= 1 ; } return res; } }
1502. 判断能否形成等差数列 思路:
1.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 class Solution { public boolean canMakeArithmeticProgression (int [] arr) { Arrays.sort(arr); int diff = arr[1 ] -arr[0 ]; int i = 0 ; while (i < arr.length-1 ) { if (arr[i+1 ] == (i+1 ) * diff + arr[0 ]) i++; else return false ; } return true ; } }
思路:
使用 “快慢指针” 思想,找出循环:“快指针” 每次走两步,“慢指针” 每次走一步,当二者相等时,即为一个循环周期。此时,判断是不是因为 1 引起的循环,是的话就是快乐数,否则不是快乐数。
注意:此题不建议用集合记录每次的计算结果来判断是否进入循环,因为这个集合可能大到无法存储;另外,也不建议使用递归,同理,如果递归层次较深,会直接导致调用栈崩溃。不要因为这个题目给出的整数是 int 型而投机取巧。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public class Solution { public int squareSum (int n) { int sum = 0 ; while (n > 0 ) { int digit = n % 10 ; sum += digit * digit; n /= 10 ; } return sum; } public boolean isHappy (int n) { int slow = n, fast = squareSum(n); while (slow != fast){ slow = squareSum(slow); fast = squareSum(squareSum(fast)); }; return slow == 1 ; } }
1790. 仅执行一次字符串交换能否使两个字符串相等
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class Solution { public boolean areAlmostEqual (String s1, String s2) { int i = 0 ; int count = 0 ; HashMap<Character, Character> dict = new HashMap <>(); while (i < s1.length()){ if (count > 2 ) return false ; if (s1.charAt(i) != (s2.charAt(i))) { if (dict.containsKey(s2.charAt(i)) && s1.charAt(i) == dict.get(s2.charAt(i))) dict.remove(s2.charAt(i)); else dict.put(s1.charAt(i), s2.charAt(i)); count ++; } i++; } if (dict.size() == 0 ) return true ; else return false ; } }
函数 589. N 叉树的前序遍历
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class Solution { public List<Integer> preorder (Node root) { transverse(root); return res; } List<Integer> res = new LinkedList <>(); void transverse (Node root) { if (root == null ) return ; res.add(root.val); for (Node child: root.children){ transverse(child); } } }
496. 下一个更大元素 I 单调栈模板 实现了一个计算下一个更大元素的函数,这里可以直接复用。因为题目说 nums1 是 nums2 的子集,那么我们先把 nums2 中每个元素的下一个更大元素算出来存到一个映射里,然后再让 nums1 中的元素去查表即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 class Solution { public int [] nextGreaterElement(int [] nums1, int [] nums2) { int [] greater = nextGreaterElement(nums2); HashMap<Integer, Integer> greaterMap = new HashMap <>(); for (int i = 0 ; i < nums2.length; i++) { greaterMap.put(nums2[i], greater[i]); } int [] res = new int [nums1.length]; for (int i = 0 ; i < nums1.length; i++) { res[i] = greaterMap.get(nums1[i]); } return res; } int [] nextGreaterElement(int [] nums) { int n = nums.length; int [] res = new int [n]; Stack<Integer> s = new Stack <>(); for (int i = n - 1 ; i >= 0 ; i--) { while (!s.isEmpty() && s.peek() <= nums[i]) { s.pop(); } res[i] = s.isEmpty() ? -1 : s.peek(); s.push(nums[i]); } return res; } }
1232. 缀点成线
1 2 3 4 5 6 7 8 9 10 11 12 13 14 int deltaX = coordinates[0 ][0 ], deltaY = coordinates[0 ][1 ];int n = coordinates.length;for (int i = 0 ; i < n; i++) { coordinates[i][0 ] -= deltaX; coordinates[i][1 ] -= deltaY; } int A = coordinates[1 ][1 ], B = -coordinates[1 ][0 ];for (int i = 2 ; i < n; i++) { int x = coordinates[i][0 ], y = coordinates[i][1 ]; if (A * x + B * y != 0 ) { return false ; } } return true ;
1588. 所有奇数长度子数组的和
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class Solution { public int sumOddLengthSubarrays (int [] arr) { int sum = 0 ; int n = arr.length; for (int i = 0 ; i < n; i++) { int leftCount = i, rightCount = n - i - 1 ; int leftOdd = (leftCount + 1 ) / 2 ; int rightOdd = (rightCount + 1 ) / 2 ; int leftEven = leftCount / 2 + 1 ; int rightEven = rightCount / 2 + 1 ; sum += arr[i] * (leftOdd * rightOdd + leftEven * rightEven); } return sum; } }
283. 移动零 思路: 可以直接复用 27. 移除元素 的解法,先移除所有 0,然后把最后的元素都置为 0,就相当于移动 0 的效果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class Solution { public void moveZeroes (int [] nums) { int slow = 0 , fast = 0 ; while (fast<nums.length){ if (nums[fast]!=0 ) { nums[slow] = nums[fast]; slow++; } fast++; } while (slow<nums.length){ nums[slow] = 0 ; slow++; } } }
1672. 最富有客户的资产总量
1 2 3 4 5 6 7 8 9 10 11 12 13 class Solution { public int maximumWealth (int [][] accounts) { int max = Integer.MIN_VALUE; for (int [] i: accounts){ int sum = 0 ; for (int j: i){ sum += j; } max = Math.max(max, sum); } return max; } }
数组 1572. 矩阵对角线元素的和
1 2 3 4 5 6 7 8 9 10 11 12 13 class Solution { public int diagonalSum (int [][] mat) { int ans = 0 ; int n = mat.length; for (int i = 0 ; i < n; i++){ for (int j = 0 ; j < n; j++){ if (j == i || j == n - i - 1 ) ans += mat[i][j]; } } return ans; } }
566. 重塑矩阵
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class Solution { public int [][] matrixReshape(int [][] mat, int r, int c) { int m = mat.length; int n = mat[0 ].length; if (m * n != r * c) { return mat; } int [][] res = new int [r][c]; int a = 0 ; int b = 0 ; for (int i = 0 ; i < r; i++) { for (int j = 0 ; j < c; j++) { if (b >= n) { b = 0 ; a++; } res[i][j] = mat[a][b]; b++; } } return res; } }
字符串 1768. 交替合并字符串
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class Solution { public String mergeAlternately (String word1, String word2) { int len1 = word1.length(); int len2 = word2.length(); char [] ca = new char [len1+len2]; int p = 0 ; int p1 = 0 ; while (p < ca.length) { if (len1 < len2 && p1 >= len1) { ca[p] = word2.charAt(p1); } else if (len1 > len2 && p1 >= len2) { ca[p] = word1.charAt(p1); } else { ca[p] = word1.charAt(p1); ca[++p] = word2.charAt(p1); } p++; p1++; } return new String (ca); } }
1678. 设计 Goal 解析器
1 2 3 4 5 class Solution { public String interpret (String command) { return command.replace("()" , "o" ).replace("(al)" , "al" ); } }
389. 找不同
1 2 3 4 5 6 7 8 9 10 11 12 class Solution { public char findTheDifference (String s, String t) { int as = 0 , at = 0 ; for (int i = 0 ; i < s.length(); ++i) { as += s.charAt(i); } for (int i = 0 ; i < t.length(); ++i) { at += t.charAt(i); } return (char ) (at - as); } }
709. 转换成小写字母
1 2 3 4 5 class Solution { public String toLowerCase (String s) { return s.toLowerCase(); } }
1309. 解码字母到整数映射
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class Solution { public String freqAlphabets (String s) { StringBuilder ans = new StringBuilder (); for (int i = 0 ; i < s.length(); i++) { if (s.indexOf('#' , i) - i ==2 ) { ans.append((char )(Integer.parseInt(s.substring(i,i+2 ))+96 )); i+=2 ; } else { ans.append((char )(96 +(s.charAt(i)-'0' ))); } } return ans.toString(); } }
953. 验证外星语词典
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 class Solution { public boolean isAlienSorted (String[] words, String order) { int [] index = new int [26 ]; for (int i = 0 ; i < order.length(); ++i) { index[order.charAt(i) - 'a' ] = i; } for (int i = 1 ; i < words.length; i++) { boolean valid = false ; for (int j = 0 ; j < words[i - 1 ].length() && j < words[i].length(); j++) { int prev = index[words[i - 1 ].charAt(j) - 'a' ]; int curr = index[words[i].charAt(j) - 'a' ]; if (prev < curr) { valid = true ; break ; } else if (prev > curr) { return false ; } } if (!valid) { if (words[i - 1 ].length() > words[i].length()) { return false ; } } } return true ; } }
链表 & 树 1290. 二进制链表转整数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class Solution { public int getDecimalValue (ListNode head) { int ans = head.val; while (head.next!=null ) {ans <<= 1 ; head = head.next; ans+=head.val;} return ans; } }
876. 链表的中间结点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class Solution { public ListNode middleNode (ListNode head) { ListNode slow = head, fast = head; while (fast != null && fast.next != null ) { slow = slow.next; fast = fast.next.next; } return slow; } }
104. 二叉树的最大深度 思路: 动态规划
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class Solution { public int maxDepth (TreeNode root) { if (root == null ) return 0 ; int leftMax = maxDepth(root.left); int rightMax = maxDepth(root.right); return 1 +Math.max(leftMax, rightMax); } }
404. 左叶子之和
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class Solution { public int sumOfLeftLeaves (TreeNode root) { transverse(root); return sum; } int sum = 0 ; void transverse (TreeNode root) { if (root == null ) return ; if (root.left != null && root.left.left == null && root.left.right == null ) { sum += root.left.val; } transverse(root.left); transverse(root.right); } }
容器&库 1356. 根据数字二进制下 1 的数目排序
1 2 3 4 5 6 7 8 9 10 11 12 13 class Solution { public int [] sortByBits(int [] arr) { int [] map = new int [arr.length]; for (int i = 0 ; i < arr.length; i++) { map[i] = Integer.bitCount(arr[i]) * 10000000 + arr[i]; } Arrays.sort(map); for (int i = 0 ; i < map.length; i++) { map[i] = map[i] % 10000000 ; } return map; } }
232. 用栈实现队列
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 class MyQueue { private Stack<Integer> s1, s2; public MyQueue () { s1 = new Stack <Integer>(); s2 = new Stack <Integer>(); } public void push (int x) { s1.push(x); } public int pop () { peek(); return s2.pop(); } public int peek () { if (s2.isEmpty()){ while (!s1.isEmpty()) s2.push(s1.pop()); } return s2.peek(); } public boolean empty () { return s1.isEmpty() && s2.isEmpty(); } }
242. 有效的字母异位词
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class Solution { public boolean isAnagram (String s, String t) { int [] cnt = new int [26 ]; if (s.length() != t.length()) return false ; else { for (int i = 0 ; i < s.length(); i++){ cnt[s.charAt(i)-'a' ]++; } for (int i = 0 ; i < t.length(); i++) { cnt[t.charAt(i)-'a' ]--; if (cnt[t.charAt(i)-'a' ] < 0 ) return false ; } return true ; } } }
217. 存在重复元素
1 2 3 4 5 6 7 8 9 10 class Solution { public boolean containsDuplicate (int [] nums) { HashSet<Integer> set = new HashSet <>(); for (int i = 0 ; i < nums.length; i++){ if (set.contains(nums[i])) return true ; set.add(nums[i]); } return false ; } }
类 & 对象 1603. 设计停车系统
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class ParkingSystem { Map<Integer, Integer> map = new HashMap <>(); public ParkingSystem (int _big, int _medium, int _small) { map.put(1 , _big); map.put(2 , _medium); map.put(3 , _small); } public boolean addCar (int ct) { if (map.get(ct) > 0 ) { map.put(ct, map.get(ct) - 1 ); return true ; } return false ; } }
303. 区域和检索 - 数组不可变
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class NumArray { private int [] preSum; public NumArray (int [] nums) { preSum = new int [nums.length+1 ]; for (int i = 1 ; i < preSum.length; i++){ preSum[i] = preSum[i-1 ] + nums[i-1 ]; } } public int sumRange (int left, int right) { return preSum[right + 1 ] - preSum[left]; } }