leetcode mt simple

Leetcode-MT-Simple

文章实际写于2021年,那个炎热的夏天。


  Leet Code 美团题库简单类总结,题目按照解法可大致分为数学法、计数法、位运算、双指针法、字符串、哈希表、栈、递归/迭代、排序法、匹配法、记忆化法、二分法、分治法、摩尔投票法、前缀和、模拟法、动态规划几大类。大部分题目可以有多种解法。

leetcode-mt-simple

数学法、计数法、位运算、双指针法、字符串、哈希表、栈、递归/迭代、排序法、匹配法、记忆化法、二分法、分治法、摩尔投票法、前缀和、模拟法、动态规划

  • 数学法: 即利用 +、-、*、/、% 等数学思想来解决,一般结合递归/迭代使用。
  • 计数法: 即通过统计元素个数来解决。如字符串中的字母个数,数组中的元素个数。
  • 位运算: 即通过 &、|、^、<<、>> 等位运算来解决。
  • 双指针法: 即通过两个指针来解决。两个指针可以同时从前往后,也可以从后往前,也可以一个双向奔赴,还有快慢指针法。
  • 字符串: 即利用字符串相关类的相关函数来解决。如 String 中的 substring()、replace()、split() 等方法;StringBuilder 的 reverse() 等方法。
  • 哈希表: 即利用哈希表的相关特性来解决。如 map key 的唯一性、set 的去重及其 contains() 方法等功能。
  • 栈: 即利用栈先进后出的特性来解决。
  • 递归/迭代: 递归/迭代可以配合大部分解法使用,在链表、树等数据结构中最常用。
  • 排序法: 即利用排序或排序的某些特性来解决。如归并排序中的合并功能,快排思想等。
  • 匹配法: 即字符串匹配。
  • 记忆化法: 记忆化搜索与动态规划类似。
  • 二分法: 即二分法。
  • 分治法: 即分治法,分而治之。
  • 摩尔投票法: 类似于计数法,一换一的思想。
  • 前缀和: 就是前缀和。
  • 模拟法: 那也就是模拟法。
  • 动态规划: 遇事不决,动态规划。

1、数学法

1.1、整数
  • 9、回文数
    回文数指一个整数,正序读和倒序读都是一样的整数。

    // 数学法、双指针法、哈希表
    // 数学法
    public static boolean isPalindrome(int n) {if (n < 0) {return false;}if (n < 10) {return true;}int temp = 0, m = n;while ( m != 0) {temp = temp * 10 + m % 10;m /= 10;}return temp == n;
    }
    
  • 202、快乐数
    对于一个整数,每一次都将其替换为其每个位置上的数字的平方和,直到变为 1,则说明其是快乐数,也有可能便不到 1,一直无限循环。

    // 数学法、双指针法、哈希表
    // 数学法 + 哈希表
    public static boolean isHappy(int n) {List<Integer> list = new ArrayList<>();while (true) {if (n == 1) {return true;}if (list.contains(n)) {return false;}list.add(n);int sum = 0;while (n > 0) {sum += Math.pow(n % 10, 2);n /= 10;}n = sum;}
    }
    
  • interview-16-05、阶乘尾数
    给定一个整数 n,求其 n 阶乘有多少个尾随零。

    // 数学法、递归/迭代
    // 数学法 + 迭代
    // 只有 2 和 5 相乘等于 10,也就是只有 2 和 5 的乘积结果会出现 0,0 ~ 10 以内 5 不可以作为任何树的因数,所以化解为求 n 由多少个 5 组成
    public static int trailingZeroes(int n) {int temp = 0;while (n > 0) {n /= 5;temp += n;}return temp;
    }
    
1.2、字符串
  • 415、字符串相加;二进制相加、链表相加
    给定两个字符串形式的数,求其和。

    // 数学法
    // 字符串相加、二进制相加、链表相加 都可以用此方法求解
    public static String add(String a, String b) {char[] m = a.toCharArray();char[] n = b.toCharArray();StringBuilder sb = new StringBuilder();int i = m.length - 1, j = n.length - 1, carry = 0;while (i >= 0 || j >= 0 || carry != 0) {carry += i >= 0 ? m[i--] - '0' : 0;carry += j >= 0 ? n[j--] - '0' : 0;sb.append(carry % 10);carry /= 10;}return sb.reverse().toString();
    }
    
  • 461、汉明距离
    汉明距离是值两个整数,其对应二进制的值的位不同的个数。

    // 数学法、动态规划
    // 数学法
    public static int hanmingDistance(int m, int n) {int length = 0;while (m != 0 || n != 0) {if (m % 2 != n % 2) {length++;}m /= 2;n /= 2;}return length;
    }
    
1.3、数组
  • Offer61、扑克牌顺子
    在若干副扑克牌中,随意抽取五张,判断其是不是顺子,即是不是连续。其中 A 用 1 表示,J、Q、K 分别用 11、12、13 表示,大小王用 0 表示,且可以代表任意数字。

    // 数学法、哈希表
    // 数学法 + 哈希表/集合
    public static boolean isStraight(int[] nums) {List<Integer> list = new ArrayList<>(5);int max = 0, min = 13;for (int item : nums) {if (item == 0) {continue;}if (list.contanins(item)) {return false;}list.add(item);max = Math.max(max, item);min = Math.min(min, item);}return max - min <= 4;
    }
    
  • Offer62、约瑟夫环
    圆圈中最后一个数字,给定 n 个数,0 ~ n - 1,从 0 开始,删除第 m 个数字,然后从下一个元素开始,再删除第 m 个数字,求最后剩下的那个数字。即约瑟夫环。

    // 数学法、递归/迭代
    // 数学法
    // f(n, m) = (f(n - 1, m) + m) % n 表示 再 n 个数字中,删除第 m 个数字最后剩下的数字
    public static boolean lastRemaining(int n, int m) {int temp = 0;for (int i = 2; i <= n; i++) {temp = (temp + m) % i;}return temp;
    }
    

2、计数法

2.1、字符串
  • 409、最长回文串
    给定一个由大小写字母构成的字符串 s,求由这些字母构成的最长回文串的长度。

    // 计数法、哈希表
    // 计数法
    public static int longestPalindrome(String s) {char[] c = s.toCharArray();int[] temp = new int[58];   // ASCII 码表中 A ~ z 的长度for (char item : c) {temp[item - 'A']++;}int length = 0;for (int item : temp) {if (item != 0) {length = (item / 2) * 2;}}return length < c.length ? length + 1 : length;
    }
    
2.2、数组
  • 645、错误的集合
    设定一个数据集 nums,其中包含了 1 ~ n 的元素,但由于复制错误导致其中一个元素重复,一个元素丢失,求重复的元素和丢失的元素。

    // 计数法、位运算、哈希表、排序法
    // 计数法
    public static int[] findErrorNums(int[] nums) {int[] temp = new int[nums.length + 1];int[] res = new int[2];for (int item : nums) {temp[item]++;}for (int item : temp) {if (item == 2) {res[0] = item;}if (item == 0) {res[1] = item;}if (res[0] > 0 && res[1] > 0) {break;}}return res;
    }
    
  • 997、小镇法官
    小镇有 n 个人,分别用 1 ~ n 表示,传言称小镇里有一个法官,法官不信任任何人,但其他人都信任这个法官,请找出他。trust[2, 4] 表示 2 信任 4。

    // 计数法、哈希表
    // 计数法
    public static int findJudge(int n, int[][] trust) {int[] temp = new int[n + 1];for (int[] item : trust) {temp[item[0]]--;temp[item[1]]++;}for (int i = 1; i < temp.length; i++) {if (temp[i] == n - 1) {return i;}}return -1;
    }
    
  • 1207、独一无二的出现次数
    给定一个整数数组 nums,请统计数组中元素的出现次数,若每个元素的出现次数都是独一无二的,则返回 true,否则返回 false。

    // 计数法、哈希表
    // 哈希表
    public static boolean uniqueOccurrences(int[] nums) {Map<Integer, Integer> map = new HashMap<>();for (int item : nums) {map.put(item, map.getOrDefault(item, 0) + 1);}return map.size() == new HashSet<>(map.values()).size();
    }
    
  • Offer03、数组中重复的数字
    给定一个长度为 n 的数组,数组元素为 0 ~ n - 1,数组中某些数字是重复的,请找出任意一个重复的元素。

    // 计数法、哈希表、排序法
    // 剑指 offer 原解
    // 1、若要求低时间,则用集合法(也就是字典法)
    // 2、若要求低空间,则用排序法(冒泡、选择、插入等空间复杂度为 O(1)的)或如下示例法
    // 3、若要求低空间且不能修改原数组,则使用二分法
    public static int findRepeatNumber(int[] nums) {int length = nums.length;for (int i = 0; i < length; i++) {int k = nums[i];if (k < 0) {k += length;}if (nums[k] < 0) {  return k;}nums[k] -= length;}return -1;
    }
    

3、位运算

  • 231、2 的幂
    给定一个整数,判断其是否为 2 的幂次方。

    // 数学法、位运算
    // 位运算 2^n & (2^n - 1) == 0
    public static boolean isPowerOfTwo(int n) {if (n <= 0) {return false;}return (n & n - 1) == 0;
    }
    
  • Offer65、不用 +、-、*、/ 做加法
    不使用 +、-、*、/ 实现加法功能。

    // 数学法、位运算
    // 位运算
    // a ^ b 异域:表示 a 和 b 的无进位求和,如 23 ^ 7 = 10;a & b 与:表示 a 和 b 的和进位,如 23 & 7 = 3
    public static int add(int a, int b) {int m = a ^ b, n = a & b;if (n == 0) {return m;}return add(m, n << 1);
    }
    

4、双指针法

4.1、字符串
  • 125、回文串
    给定一个字符串,验证其是否为回文串,只考虑字母数字,忽略大小写。

    // 双指针法、哈希表
    // 双指针法
    public static boolean isPalindrome(String s) {String temp = s.replaceAll("[A-Za-z0-9]", "");for (int i = 0, j = temp.length() - 1; i < j; i++, j--) {if (temp.charAt(i) != temp.charAt(j)) {return false;}}return true;
    }
    
  • 344、反转字符串
    给定一个字符串,将其中的字符串反转过来。

    // 双指针法
    public static void reverseString(char[] c) {for (int i = 0, j = c.length - 1; i < j; i++, j--) {char temp = c[i];c[i] = c[j];c[j] = temp;}
    }
    
  • 459、重复的子字符串
    给定一个字符串 s,判断其是否可以由其某个子字符串重复多次构成。

    // 双指针、匹配
    // 双指针
    public static boolean repeatedSubstringPattern(String s) {char[] c = s.toCharArry();for (int i = 1; i < c.length / 2; i++) {if (c.length % i != 0) {continue;}int m = 0, n = m + i;while (n < c.length) {if (c[m] != c[n]) {break;}m++;n++;}if (n == c.length) {return true;}}return false;
    }
    
  • 1047、删除字符串中所有的相邻重复项
    给定一个字符串,删除其中所有相邻重复项。

    // 双指针法、栈
    // 双指针
    public static String removeDuplicates(String s) {char[] c = s.toCharArray();int index = -1;for (int i = 0; i < c.length; i++) {if (index != -1 && c[index] == c[i]) {index--;} else {c[++index] = c[i];}}return String.copyValueOf(c, 0, index + 1);
    }
    
4.2、数组
  • 26、移除有序数组中的重复项
    给定一个升序数组 nums,请原地移除重复出现的元素,且使元素的相对顺序保持一致。若最终结果为 k 个,则不考虑 k 及之口的元素。

    // 双指针法
    public static int removeDuplicates(int[] nums) {int i = 0;for (int j = 1; j < nums.length; ) {if (nums[i] == nums[j]) {j++;} else {i++;if (i != j) {nums[i] = nums[j];}j++;}}return i + 1;
    }
    
  • 27、移除指定元素
    给定一个数组及一个值,原地移除该元素。

    // 双指针法
    public static int removeElement(int[] nums, int n) {int index = 0;for (int i = 0; i < nums.length; i++) {if (nums[i] != n) {nums[index++] = nums[i];}}return index;
    }
    
  • 283、移动数组元素零
    给定一个数组,将元素 0 移至末尾。

    // 双指针法
    public static void moveZeroes(int[] nums) {int index = 0;for (int i = 0; i < nums.length; i++) {if (nums[i] != 0) {if (index != i) {nums[index] = nums[i];nums[i] = 0;}index++;}}
    }
    
  • 350、数组交集
    给定两个数组,返回数组交集,若元素出现多次,则以出现次数较小的为准。

    // 双指针法、哈希表、排序法
    // 双指针法
    public static int[] intersect(int[] m, int[] n) {Arrays.sort(m);Arrays.sort(n);List<Integer> list = new ArrayList<>();for (int i = 0, j = 0; i < m.length && j < n.length; ) {if (m[i] < n[j]) {i++;} else if (m[i] > n[j]) {j++;} else {list.add(m[i]);i++;j++;}}int[] temp = new int[list.size()];int index = 0;for (int item : list) {temp[index++] = item;}return temp;
    }
    
  • 557、反转字符串中的单词
    给定一个字符串,反转字符串中每个单词的字母顺序。

    // 双指针
    public static String reverseWords(String s) {char[] c = s.toCharArray();int i, j;for (i = 0, j = 0; j < c.length(); ) {if (c[j] != ' ') {j++;} else {reverse(c, i, j);i = j + 1;j = i;}}reverse(c, i, j - 1);return new String(c);
    }public static void reverse(char[] c, int start, int end) {while (start < end) {char temp = c[start];c[start] = c[end];c[end] = temp;start++;end--;}
    }
    
  • 1470、重新排列数组
    重新排列数组x1x2x3…xn y1y2y3…yn => x1y2x2y2x3yy3…xnyn。

    // 双指针
    public static int[] shuffle(int[] nums, int n) {int[] temp = new int[n * 2];int index = 0;for (int i = 0, j = n; j < nums.length; i++, j++) {temp[index++] = nums[i];temp[index++] = nums[j];}return temp;
    }
    
  • Offer21调整数组元素使奇数在偶数前面
    嗯,就像题目那样。

    // 双指针
    public static int[] exchange(int[] nums) {for (int i = 0, j = nums.length - 1; i < j;) {if (nums[i] % 2 != 0) {i++;}if (nums[j] % 2 == 0) {j--;}if (i < j && nums[i] % 2 == 0 && nums[j] % 2 != 0) {int temp = nums[i];nums[i] = nums[j];nums[j] = temp;i++;j--;}}return nums;
    }
    
  • Offer57-II、和为 s 的连续正整数序列
    和为 s 的连续正整数序列。

    // 双指针
    public static int[][] findContinuousSequence(int target) {int[][] res = new int[0][];for (int i = 1, j = 2; j < target; ) {int sum = ((i + j) * ( j - i + 1)) / 2;if (sum == target) {int[] temp = new int[j - 1];int index = 0, start = i;while (start <= j) {temp[index++] = start++;}res = Arrays.copyOf(res, res.length + 1);res[res.length - 1] = temp;i++;} else if (sum < target) {j++;} else {i++;}}return res;
    }
    
4.3、链表
  • 141、环形链表
    给定一个链表,判断其是否为环形链表。

    // 双指针、哈希表
    // 双指针(快慢指针)
    public static boolean hasCycle(Node node) {Node slow = node, fast = node;while (slow != null && fast != null && fast.next != null) {slow = slow.next;fast = fast.next.next;if (slow == fast) {return true;}}return false;
    }
    
  • 160、Offer52、相交链表
    给定两个链表,判断其是否相交,若相交则返回相交节点,若不想交则返回 null。

    // 双指针、哈希表
    // 双指针
    public static Node getIntersectionNode(Node node1, Node node2) {Node first = node1, second = node2;while (first != second) {first = first != null ? first.next : node2;second = second != null ? second.next : node1;}return first;
    }
    
  • Offer22、链表中倒数第 k 个节点
    给定一个链表,返回链表中倒数第 k 个节点。

    // 双指针
    public static Node getKthFromEnd(Node node, int k) {Node first = node, second = node;while (k > 0 && second != null) {second = second.next;k--;}while (second != null) {first = first.next;second = second.next;}return first;
    }
    

5、字符串

  • Offer58-I、反转字符串中的单词顺序
    给定一个字符串,反转字符串中的单词顺序。

    // 双指针、字符串
    // 字符串
    public static String reverseWords(String s) {if (s == null || s.length() == 0 || s.replaceAll(" ", "").length() == 0) {return "";}String[] temp = s.split(" ");StringBuilder sb = new StringBuilder();for (int i = temp.length - 1; i >= 0; i--) {if (!temp[i].equals("")) {sb.append(temp[i]).append(" ");}}return sb.substring(0, sb.length() - 1);
    }
    
  • 14、最长公共前缀
    给定一个字符串数组,求其最长公共前缀。

    // 字符串
    public static String longestCommonPrefix(String[] s) {String prefix = s[0];for (String item : s) {while (!item.startsWith(prefix)) {if (prefix.length() == 0) {return "";}prefix = prefix.substring(0, prefix.length() - 1);}}return prefix;
    }
    
  • 1556、千位分隔数
    给定一个整数 n,返回其千位分隔后的字符串。

    // 字符串
    public static String thousandSeparator(int n) {StringBuilder sb = new StringBuilder(String.valueOf(n));if (sb.length() <= 3) {return sb.toString();}for (int i = sb.length() - 1 - 3; i >= 0; i -= 3) {sb.insert(i + 1, '.');}return sb.toString();
    }
    

6、哈希表

  • 771、宝石与石头
    给定两个字符串 j 和 s,j 中的每个字符代表了一种宝石,s 代表你拥有的石头,统计你拥有的石头中的宝石的数量。

    // 哈希表
    public static int numJewelsInStones(String j, String s) {Set<Character> set = new HashSet<>(j.length());for (char c : j.toCharArray()) {set.add(c);}int num = 0;for (char c: s.toCharrray()) {if (set.contains(c)) {num++;}}return num;
    }
    
  • 859、亲密字符串
    给定两个字符串 s 和 g,如果只交换 s 中两个字符的位置久能得到与 g 相等的结果,那就认为 s 和 g 是亲密字符串。

    // 哈希表
    public static boolean buddyStrings(String s, String g) {if (s.length() != g.length()) {return false;}if (s.equals(g)) {int[] temp = new int[26];  // s g 只包含小写字母for (char c : s.toCharAray()) {temp[c - 'a']++;if (temp[c - 'a'] > 1) {return true;}}return false;} else {int first = -1, second = -1;for (int i = 0; i < s.length(); i++) {if (s.charAt(i) != g.charAt(i)) {if (first == -1) {first = i;} else if (second == -1) {second = i;} else {return false;}}}return first != -1 && second != -1 && s.charAt(second) == g.charAt(first) && s.charAt(first) == g.charAt(second);}
    }
    
  • 1、两数之和
    给定一个整数数组和一个目标整数,请返回数组中和为目标整数的元素下标。

    // 哈希表
    public static int[] twoSum(int[] nums, int target) {Map<Integer, Integer> map = new HashMap<>(nums.length());int[] res = new int[2];for (int i = 0; i < nums.length; i++) {if (map.containsKey(nums[i])) {res[0] = map.get(nums[i]);res[1] = i;} else {map.put(target - nums[i], i);}}return res;
    }
    

7、栈

7.1、链表
  • Offer06、从尾到头打印链表
    给定一个链表,从尾到头打印链表。

    // 双指针、栈、递归/迭代
    // 栈
    public static int[] reversePrint(Node node) {Stack<Integer> stack = new Stack<>();while (node != null) {stack.push(node.value);node = node.next;}int[] res = new int[stack.size()];int index = 0;while (!stack.isEmpty()) {res[index++] = stack.pop();}return res;
    }
    
7.2、字符串
  • 20、有效的括号
    给定一个只包含 ‘(’、‘)’、‘[’、‘]’、‘{’、‘}’ 字符的字符串,判断其是否有效。有效定义为,左括号必须在对应位置上有正确的右括号。

    // 栈
    public static boolean isValid(String s) {Stack<Character> stack = new Stack<>();for (char c : s.toCharArray()) {if (c == '(') {stack.push(')');} else if (c == '[') {stack.push(']');} else if (c == '{') {stack.push('}');} else if (stack.isEmpty() || c!= stack.pop()) {return false;}}return stack.isEmpty();
    }
    
7.3、栈
  • 716、最大栈;Offer30、最小栈
    设计一个最大栈数据结构,既支持栈操作,又能查找栈中最大元素。

    // 双栈
    // 一个栈用来提供栈操作,另一个栈用来提供最大元素操作,利用栈的先进后出的特性
    
  • 232、Offer09、实现队列
    用双栈实现队列。

    // 双栈
    // 一个栈用来入列,一个栈用来出列。
    

8、递归/迭代

8.1、链表
  • 83、删除排序链表中的重复元素
    给定一个排序链表,删除其中重复的元素。

    // 栈、递归/迭代
    // 递归/迭代
    public static Node deleteDuplicates(Node node) {Node last = node;Node temp = last.next;while (last != null && temp != null) {if (last.value != temp.value) {last.next = temp;last = last.next;}temp = temp.next;}last.next = null;return node;
    }
    
  • 206、Offer24、反转链表
    给定一个链表,反转链表,返回反转后的头节点。

    // 栈、递归/迭代
    // 迭代
    public static Node reverseList(Node node) {Node prev = null, curr = node, temp;while (curr != null) {temp = curr.next;curr.next = prev;prev = curr;curr = temp;}return prev;
    }
    
  • 237、Offer18、删除链表节点
    给定一个链表及一个目标值,删除链表中节点值等于目标值的一个节点。

    // 栈、递归/迭代
    // 迭代
    public static Node deleteNode(Node node, int value) {if (node == null) {return null;}Node root;if (node.value == value) {root = node.next;} else {root = node;}while (node.next != null) {if (node.next.value == value) {node.next = node.next.next;break;}node = node.next;}return root;
    }
    
8.2、二叉树
  • 144、前;94、中;145、后;深;广遍历

    // 前中后深广遍历就不用多说了吧
    
  • 108、有序数组转化为二叉搜索树
    给定一个有序数组,将其转化为二叉搜索树。

    // 递归/迭代、分治
    // 递归
    public static Tree sortedArrayToBST(int[] nums) {return nums == null ? null : build(nums, 0, nums.length - 1);
    }public static Tree build(int[] ums, int left, int right) {if (left > right) {return null;}int mid = left + (right - left) / 2;Tree tree = new Tree(nums[mid]);tree.left = build(nums, left, mid - 1);tree.right = build(nums, mid + 1, right);return tree;
    }
    
  • 104、二叉树的最大;111、最小深度;112、路径总和
    给定一个二叉树,求其最大深度。

    // 递归/迭代、深、广
    public static int maxDepth(Tree tree) {return tree == null ? 0 : Math.max(tree.left, tree.right) + 1;
    }// 最小深度
    public static int minDepth(Tree tree) {if (tree == null) {return 0;}if (tree.left != null && tree.right == null) {return minDepth(tree.left) + 1;}if (tree.left == null && tree.right != null) {return minDepth(tree.right) + 1;}return Math.min(minDepth(tree.left), minDepth(tree.right)) + 1;
    }// 路径总和
    // 给定一个二叉树根节点和一个目标值,判断二叉树的每个叶子节点的总和中是否有和目标值相等的。
    public static boolean hasPathSum(Tree tree, int target) {if (tree == null) {return false;}if (tree.left == null && tree.right == null) {return targte - tree.value == 0;}return hasPathSum(tree.left, target - tree.value) || hasPathSum(tree.right, target - tree.value);
    }
    
  • 101、Offer28、对称二叉树
    给定一个二叉树,判断其是否为对称二叉树。

    // 递归
    public static boolean isSymmetric(Tree tree) {return tree == null ? true : check(tree.left, tree.right);
    }public static boolean check(Tree left, Tree right) {if (left == null || right == null) {return false;}return left.value == right.value && check(left.left, right.right) && check(left.right, right.left);
    }
    
  • 226、翻转二叉树
    给定一颗二叉树,翻转其左右节点。

    // 前、中、后、深、广、笨比
    // 前
    public static Tree before(Tree tree) {if (tree == null) {return null;}Tree temp = tree.left;tree.left = brfore(tree.right);tree.right = before(temp);return tree;
    }// 中
    public static Tree middle(Tree tree) {if (tree == null) {return null;}middle(tree.left);Tree temp = tree.left;tree.left = tree.right;tree.right = temp;middle(tree.left);return tree;
    }// 后
    public static Tree after(Tree tree) {if (tree =null) {return null;}Tree left = after(tree.left);Tree right = after(tree.right);tree.left = right;tree.right = left;return tree;
    }// 广
    public static Tree bfs(Tree tree) {if (tree == null) {return null;}Queue<Tree> queue = new LinkedList<>();queue.add(tree);while (!queue.isEmpty()) {Tree tree1 = tree.poll();Tree temp = tree1.left;tree1.left = tree1.right;tree1.right = temp;if (tree1.left != null) {queue.add(tree1.left);}if (tree1.right != null) {queue.add(tree1.right);}}return tree;}
    
  • 617、合并二叉树
    给定两个二叉树,合并二叉树。

    // 递归
    public static Tree mergeTrees(Tree tree1, Tree tree2) {if (tree1 == null) {return tree2;}if (tree2 == null) {return tree1;}tree1.value += tree2.value;tree1.left = mergeTrees(tree1.left, tree2.left);tree1.right = mergeTrees(tree1.right, tree2.right);return tree1;
    }
    
  • 257、二叉树的所有路径(深)
    给定一颗二叉树,返回其所有路径。

    // 深
    public static List<String> binaryTreePaths(Tree tree) {List<String> list = new ArrayList<>();StringBuildr sb = new StringBuilder();path(tree, list, sb);return list;
    }public static void path(Tree tree, List<String> list, StringBuilder sb) {if (tree == null) {return;}sb.append(tree.value).append('->');if (tree.left != null) {path(tree.left, list, new StringBuilder(sb));}if (tree.right != null) {path(tree.right, list, new StringBuilder(sb));}if (tree.left == null && tree.right == null) {list.add(sb.substring(0, sb.length() - 2));return;}
    }
    
  • 543、二叉树的直径(深)
    给定一颗二叉树,求其直径。二叉树直径为任意两个叶节点之间的路径长度。

    // 深
    int max = 0;
    public static int diameterOfBinaryTree(Tree tree) {depth(tree);return max;
    }public static int depth(Tree tree) {if (tree == null) {return 0;}int leftDepth = tree.left != null ? depth(tree.left) + 1 : 0;int rightDepth = tree.right != null ? depth(tree.right) + 1 : 0;max = Math.max(max, leftDepth + rightDepth);return Math.max(leftDepth, rightDepth);
    }
    
  • 572、另一棵树的子树(深)
    给定两颗二叉树,判断第二颗是否为第一颗的子树。

    // 深
    public static boolean isSubtree(Tree, tree1, Tree tree2) {if (tree1 == null) {return false;}return isSame(tree1, tree2) || isSame(tree1.left, tree2) || isSame(tree1.right, tree2);
    }public static boolean isSame(Tree tree1, Tree tree2) {if (tree1 == null && tree2 == null) {return treu;}if (tree1 == null || tree2 == null) {return false;}return tree1.value == tree2.value && isSame(tree1.left, tree2.left) && isSame(tree1.right, tree2.right);
    }
    
  • Offer55-II、平衡二叉树(深)
    给定一颗二叉树,若其任意节点的左右子树的深度差不超过 1,则称为平衡二叉树。

    // 深(自顶向下递归)
    public static boolean isBalanced(Tree tree) {if (tree == null) {return treu;}if (Math.abs(depth(tree.left) - depth(tree.right)) > 1) {return false;}return isBalanced(tree.left) && isBalanced(tree.right);// 自底向上递归return depth1(tree) >= 0;
    }// 自底向上递归
    public static int depth1(Tree tree) {if (tree == null) {return 0;}int leftDepth = depth1(tree.left);int rightDepth = depth1(tree.right);if (leftDepth == -1 || rightDepth == -1 || Math.abs(leftDepth - rightDepth) > 1) {return -1;}return Math.max(leftDepth, rightDepth) + 1;
    }public static int depth(Tree) {return tree == null ? 0 : Math.max(tree.left, tree.right) + 1;
    }
    
  • 637、二叉树的层平均值(广)
    给定一颗二叉树,返回其层平均值。

    // 广
    // 广度优先遍历 求每一层平均值 代码过于简单 不予展示
    
  • Offer54、二叉搜索树的第 k 大节点(反中序)
    给定一颗二叉搜索树,返回其第 k 大节点。

    // 反中序
    int count = 0, value = 0;
    public static int k(Tree tree, int k) {if (tree == null) {return -1;}middle(tree, k);return value;
    }public static void middle(Tree tree, int k) {if (tree.right != null) {middle(tree.right, k);}if (++count == k) {value = tree.value;break;}if (tree.left != null) {middle(tree.left, k);}
    }
    
  • 559、N 叉树的最大深度(深、广)
    给定一颗 n 叉树,返回其最大深度。

    // 深/广
    // 深
    public static int dfs(Tree tree) {if (tree == null) {return 0;}int depth = 0;for (Tree item : tree.children) {depth = Math.max(depth, dfs(item));}return depth + 1;
    }// 广
    public static int bfs(Tree tree) {if (tree == null) {return 0;}if (tree.children.size == 0) {return 1;}int depth = 0;Queue<Tree> queue = new LinkedList<>();queue.add(tree);while (!queue.isEmpty()) {depth++;int size = queue.size();while (size > 0) {Tree temp = queue.poll();if (temp.chiildren,.size > 0) {queue.addAll(temp.children);}size--;}}return depth;
    }
    

9、排序法

9.1、数组
  • 88、合并有序数组
    给定 两个升序数组,合并数组,并使元素保持升序顺序。

    // 双指针法、排序法
    // 排序法(归并合并)
    public static int[] merge(int[] m, int[] n) {int[] res = new int[m.length + n.length];int i = 0, j = 0, index = 0;while (i < m.length && j < n.length) {res[index++] = m[i] < n[j] ? m[i++] : n[j++];}if (i < m.length) {res[index++] = m[i++];}if (j < n.length) {res[index++] = n[j++];}return res;
    }
    
  • Offer40、最小的 k 个数(快排)
    给定一个整数数组和一个整数 k,k 小于数组的长度,返回数组中最小的 k 个数。

    // 排序法(快排思想)
    public static int[] getLeastNumbers(int[] nums, int k) {if (nums.length == 0) {return new int[0];}return min(nums, 0, nums..length - 1, k);
    }public static int[] min(int[] nums, int left, int right, int k) {int index = quick(nums, left, right);if (index + 1 == k) {return Arrays.copyOf(nums, 0, k);}return index + 1 < k ? min(nums, index + 1, right, k) : min(nums, left, index - 1, k);
    }public static int quick(int[] nums, int left, int right) {int key = nums[left];int i = left, j = right;while (i < j) {while (i < j && nums[j] >= key) {j--;}while (i < j && nums[i] <= key) {i++;}if (i < j) {int temp = nums[i];nums[i] = nums[j];nums[j] = temp;}}nums[left] = nums[i];nums[i] = key;return i;
    }
    
9.2、链表
  • 21、Offer25、合并有序链表
    合并两个有序链表。

    // 排序法(归并合并思想)
    public static Node mergeTwoLists(Node node1, Node node2) {if (node1 == null) {return node2;}if (node2 == null) {return node1;}Node root = new Node(-1);Node node = root;while (node1 != null && node2 != null) {if (node1.value <= node2.value) {node.next = node1;node1 = nnode1.next;} else {node.next = node2;node2 = node2.next;}node = node.next;}if (node1 != null) {node.next = node1;}if (node2 != null) {node.next = node2;}return root.next;
    }
    

10、匹配法

  • 28、strStr()
    实现 strStr() 方法。

    // 字符串匹配 直接参考五大匹配算法(BF、RK、KMP、BM、Sunday)
    

11、记忆化法

// 记忆化法皆可用动态规划解决

12、二分法

  • 35、搜索插入位置
    给定一个有序数组和一个整数,返回该整数在数组中的索引,若不存在于数组,则返回其插入位置。

    // 二分法
    public static int searchInsert(int[] nums, int key) {if (key < nums[0]) {return 0;} else if (key > nums[nums.length - 1]) {return nums.length;} ele {return binary(nums, 0, nums.length - 1, key);}
    }public static int binary(int[] nums, int left, int right, int key) {if (left == right) {if (key <= nums[left]) {return left;} else {return left + 1;}} else if (left < right) {int mid = left + (right - left) / 2;if (key == nums[mid]) {return mid;} else if (key < nums[mid]) {return binary(nums, left, mid - 1, key);} else {return bianry(nums, mid + 1, right, key);}} else {return left;}
    }
    
  • 69、x 的平方根
    给定一个整数 x,在不使用任何库函数的情况下,返回 x 的算数平方根。

    // 二分法
    public static int mySqrt(int x) {int left = 0, right = x, res = -1;while (left <= right) {int mid = left + (right - left) / 2;if ((long) mid * mid <= x) {res = mid;left = mid + 1;} else {right = mid - 1;}}return res;
    }
    
  • 704、二分查找
    二分查找。

    // 二分查找 代码见七大查找算法之二分查找
    
  • 852、山脉数组的峰顶索引
    给定一个山脉数组,返回其峰顶索引值,即返回最大值索引。

    public static int peakIndexInMountainArray(int[] nums) {int left = 0, right = arr.length - 1;while (left < right) {int mid = left + (right - left) / 2;if (nums[mid] > nums[mid - 1] && nums[mid] > nums[mid + 1]) {return mid;} else if (nums[mid] < nums[mid - 1]) {right = mid - 1;} else {left = mid + 1;}}return - 1;
    }
    

13、分治法

// 皆可用其它方法解决

14、摩尔投票法

  • 169、Offer39、多数元素
    给定一个数组,求出现次数超过一半元素。

    // 计数法、哈希表、分治法、摩尔投票法
    // 摩尔投票法
    public static int majorityElement(int[] nums) {int count = 1, curr = nums[0];for (int i = 1; i < nums.length; i++) {if (nums[i] == curr) {count++;} else {count--;if (count == 0) {if (i< nums.length - 1) {curr = nums[i + 1];} else {return -1;}}}}return count;
    }
    

15、前缀和

  • 303、区域检索-数组不可变
    利用前缀和来作为结果。

    // 代码被扣了
    

16、模拟法

  • 867、转置矩阵
    转置矩阵,即将矩阵的行换成列,列换成行。

    // 模拟法
    public static int[][] transpose(int[][] nums) {if (nums.length == 0) {return null;}int[][] res = new int[nums[0].length][nums.length];for (int i = 0; i < nums.length; i++) {for (int j = 0; j < nums[i].length; j++) {res[j][i] = nums[i][j];}}return res;
    }
    
  • Offer29、顺时针打印矩阵
    给定一个矩阵,顺时针打印矩阵内元素。

    // 模拟法
    public static int[] spiralOrder(int[][] nums) {if (nums.length == 0) {return new int[] {};}int high = nums.length, width = nums[0].length;int[] res = new int[high * width];int right = width - 1, down = high - 1, left = 0, up = 0;int index = 0, i = 0, j = 0;while (left <= right && up <= down) {// 对应存在以最中心元素中心对称的情况if ((right == left) && (down == up) && (right == down)) {res[index++] = nums[i][j];break;}while (j < right) {res[index++] = nums[i][j++];}right--;while (i < down) {res[index++] = nums[i++][j];}down--;while (j > left && index < res.length) {res[index++] = nums[i][j--];}left++;while (i > up && index < res.length) {res[index++] = nums[i--][j];}up++;i++;j++;}return res;
    }
    

17、动态规划

17.1、整数
  • 118、杨辉三角
    杨辉三角,在杨辉三角中,每个数字的值等于它左上方和右上方的和。给定一个整数 n,返回 n 行杨辉三角。

    // 动态规划
    public static int[][] generate(int n) {int[][] dp = new int[n][0];for (int i = 0; i < n; i++) {int[] temp = new int[i + 1];dp[i] = temp;for (int j = 0; j <= i; j++) {if (i == 0 || j == 0) {dp[i][j] = 1;} else {if (j <= i / 2) {dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j];} else {dp[i][j] = dp[i][i - j];}}}}return dp;
    }
    
  • 509、Offer10I、斐波那契数列
    斐波那契数列 f(n) = f(n - 2) + f(n + 1)。

    // 递归/迭代、动态规划
    // 动态规划
    public static int fibonacci(int n) {if (n < 2) {return n;}int prePre = 0, pre = 1, fn = 0;for (int i = 1; i < n; i++) {fn = (prePre + pre) % 1000000007;prePre = pre;pre = fn;}return fn;
    }
    
  • 70、爬楼梯;Offer10II、跳台阶
    小丸子爬楼梯与跳台阶,可以一次爬一个台阶,也可以一次爬两个台阶,求对于有 n 个台阶的楼梯,小丸子有多少中爬楼梯方案。

    // 动态规划
    public static int climbStairs(int n) {// 若是跳台阶 小丸子会原地蹦一下// if (n == 0) {//     return 1;// }if (n <= 2) {return n;}int a = 1, b = 2, temp = 0;for (int i = 3; i <= n; i++) {temp = (a + b) % 1000000007;a = b;b = temp;}return temp;
    }
    
  • interview-08-01、三步问题
    小丸子上楼梯,小丸子长大了,可以一次上一个,也可以一次上两个,也可以一次上三个。对于有 n 个台阶的楼梯,小丸子有多少中爬楼梯方案。

    // 动态规划
    public static int waysToStep(int n) {if (n < 3) {return n;}if (n == 3) {return 4;}int mod = 1000000007;int[] dp = new int[n + 1];dp[1] = 1;dp[2] = 2;dp[3] = 4;for (int i = 4; i <= n; i++) {dp[i] = (dp[i - 3] + dp[i - 2]) % mod + dp[i - 1];dp[i] %= mod;}return dp[n];
    }
    
17.2、数组
  • 53、Offer42、最大连续子段和
    给定一个数组,求其最大连续子段和。

    // 动态规划
    public static int maxSubArray(int[] nums) {int max = nums[0];for (int i = 1; i < nums.length; i++) {nums[i] += Math.max(nums[i], 0);max = Math.max(max, nums[i]);}return max;
    }
    
  • 121、买卖股票问题
    给定一个数组,nums[i] 表示第 i 天股票的价格。求股票买卖的最大利润。

    // 动态规划
    public static int maxProfit(int[] nums) {int max = 0, minPrice = nums[0];for (int i = 1; i < nums.length; i++) {max = Math.max(max, nums[i] - minPrice);minPrice = Math.min(minPrice, nums[i]);}return max;
    }
    
  • 392、判断子序列
    给定两个字符串 s 和 t,判断 s 是否为 t 的子序列。

    // 双指针、动态规划
    // 动态规划
    // 转化为最短编辑距离问题,最短编辑距离问题中 s => t 可以经过修改、插入、删除来完成,而在这个问题中 s => t 只能通过插入
    public static boolean isSubsequence(String s, String t) {char[] a = s.toCharArray();char[] b = t.toCharArray();int[][] dp = new int[a.length + 1][b.length + 1];for (int i = 1; i < a.length + 1; i++) {for (int j = 1; j < b.length + 1; j++) {if (a[i - 1] == b[j - 1]) {dp[i][j] = dp[i - 1][j - 1] + 1;} else {dp[i][j] = dp[i][j - 1];}}}return dp[a.length][b.length] == s.length();
    }
    
  • LCP07、传递信息
    给定一个整数 n,表示 n 个小朋友,编号从 0 ~ n - 1;给定一个二维数组,其中第二维 [2, 6] 表示信息可以从 2 传到 6;给定一个整数 k 表示传递的次数。求信息经过 k 次传播传到 n - 1 处的方案数。

    // 动态规划
    public static int numWays(int n, int[][] relation, int k) {int[][] dp = new int[k + 1][n];dp[0][0] = 1;  // 可以理解为刚开始信息的持有者for (int i = 1; i < k + 1; i++) {for (int[] temp : relation) {dp[i][temp[1]] += dp[i - 1][temp[0]];}}return dp[k][n - 1];
    }
    

@XGLLHZ - 吴奇隆 -《祝你一路顺风》.mp3

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/771630.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于nodejs+vue家装一体化平台python-flask-django-php

提高现下家装一体化平台的准确度&#xff0c;同时降低经济波动带来的不良影响&#xff0c;希望本文能对广大学者的研究提供参考。 前端技术&#xff1a;nodejsvueelementui, Express 框架于Node运行环境的Web框架, 语言 node.js 框架&#xff1a;Express 前端:Vue.js 数据库&am…

喜获千万元价值补贴,探索 AI 领域新应用:Zilliz 全力支持 AI 初创企业

价值 1000 万元的大额补贴&#xff01;得到领先全行业的向量数据库团队支持&#xff01;尽享独家生态资源&#xff01;「Zilliz AI 初创计划」正式开启&#xff01; 「Zilliz AI 初创计划」是 Zilliz 面向 AI 初创企业推出的一项扶持计划&#xff0c;预计提供总计 1000 万元的 …

书生·浦语大模型实战营——两周带你玩转微调部署评测全链路

引言 人工智能技术的发展日新月异&#xff0c;其中大模型的发展尤其迅速&#xff0c;已然是 AI 时代最炙手可热的当红炸子鸡。 然而&#xff0c;大模型赛道对于小白开发者来说还是有不小的门槛。面对内容质量参差不齐的课程和实际操作中遇到的问题&#xff0c;许多开发者往往…

2核4g服务器能支持多少人访问?阿里云2核4g服务器在线人数

阿里云2核4G服务器多少钱一年&#xff1f;2核4G配置1个月多少钱&#xff1f;2核4G服务器30元3个月、轻量应用服务器2核4G4M带宽165元一年、企业用户2核4G5M带宽199元一年。可以在阿里云CLUB中心查看 aliyun.club 当前最新2核4G服务器精准报价、优惠券和活动信息。 阿里云官方2…

【PCL】mac下安装PCL的安装与配置

【PCL】mac下安装PCL的安装与配置 PCL PCL官方文档 PCL&#xff08;Point Cloud Library&#xff09;是在吸收了前人点云相关研究基础上建立起来的大型跨平台开源C编程库&#xff0c;它实现了大量点云相关的通用算法和高效数据结构&#xff0c;涉及到点云获取、滤波、分割、配…

知识图谱推理算法综述(上):基于距离和图传播的模型

背景 知识图谱系统的建设需要工程和算法的紧密配合&#xff0c;在工程层面&#xff0c;去年蚂蚁集团联合 OpenKG 开放知识图谱社区&#xff0c;共同发布了工业级知识图谱语义标准 OpenSPG 并开源&#xff1b;算法层面&#xff0c;蚂蚁从知识融合&#xff0c;知识推理&#xff…

底部填充胶在汽车电子领域的应用有哪些?

底部填充胶在汽车电子领域的应用有哪些&#xff1f; 在汽车电子领域&#xff0c;底部填充胶被广泛应用于IC封装等&#xff0c;以实现小型化、高聚集化方向发展。 底部填充胶在汽车电子领域有多种应用&#xff0c;包括以下方面&#xff1a; 传感器和执行器的封装&#xff1a;汽车…

AJAX(一):初识AJAX、http协议、配置环境、发送AJAX请求、请求时的问题

一、什么是AJAX 1.AJAX 就是异步的JS和XML。通过AJAX 可以在浏览器中向服务器发送异步请求&#xff0c;最大的优势&#xff1a;无刷新获取数据。AJAX 不是新的编程语言&#xff0c;而是一种将现有的标准组合在一起使用的新方式。 2.XML 可扩展标记语言。XML被设计用来传输和…

工业级POE交换机的SSH配置步骤

工业级POE交换机的SSH&#xff08;Secure Shell&#xff09;配置可以通过以下步骤进行&#xff1a; 1. 连接到POE交换机&#xff1a;使用一个支持SSH协议的终端工具&#xff08;如PuTTY&#xff09;连接到POE交换机的管理接口。 2. 登录到POE交换机&#xff1a;输入正确的用户…

详解Java 中的 Lambda 表达式

引言&#xff1a; Lambda 表达式是 Java 8 中引入的一个重要特性&#xff0c;它可以使代码更加简洁、易读&#xff0c;并且更加具有函数式编程风格。Lambda 表达式本质上是一个匿名函数&#xff0c;它可以作为方法参数传递&#xff0c;也可以直接赋值给一个变量。 一、Lambda 表…

【数据结构与算法】直接插入排序和希尔排序

引言 进入了初阶数据结构的一个新的主题——排序。所谓排序&#xff0c;就是一串记录&#xff0c;按照其中的某几个或某些关键字的大小&#xff08;一定的规则&#xff09;&#xff0c;递增或递减排列起来的操作。 排序的稳定性&#xff1a;在一定的规则下&#xff0c;两个值…

电子方案:打地鼠

打地鼠玩具是一种经典的儿童游戏&#xff0c;它结合了电子技术来增加娱乐性和互动性。 电子技术的集成使得打地鼠玩具不仅能够提供基本的娱乐功能&#xff0c;还能够提供更多的互动性和游戏性。随着技术的发展&#xff0c;打地鼠玩具可能会包含更多的高级功能&#xff0c;如无…

如何使用 JavaScript 导入和导出 Excel

前言 在现代的Web应用开发中&#xff0c;与Excel文件的导入和导出成为了一项常见而重要的任务。无论是数据交换、报告生成还是数据分析&#xff0c;与Excel文件的交互都扮演着至关重要的角色。本文小编将为大家介绍如何在熟悉的电子表格 UI 中轻松导入 Excel 文件&#xff0c;…

Airflow【部署 01】调度和监控工作流工具Airflow官网Quick Start实操(一篇学会部署Airflow)

Airflow官网Quick Start实操 1.环境变量设置2.使用约束文件进行安装3.启动单机版3.1 快速启动3.2 分步骤启动3.3 启动后3.4 服务启动停止脚本 4.访问4.1 登录4.2 测试 来自官网的介绍&#xff1a; https://airflow.apache.org/ Airflow™是一个由社区创建的平台&#xff0c;以…

FFmpeg+mediamtx 实现将本地摄像头推送成RTSP流

文章目录 概要推流过程实现过程安装FFmpeg安装Mediamtx 启动推流 概要 FFmpegmediamtx实现将本地摄像头推送成RTSP流 FFmpeg 版本号为&#xff1a;N-114298-g97d2990ea6-20240321 mediamtx 版本号为&#xff1a;v1.6.0 推流过程 摄像头数据&#xff0c;经过ffmpeg的推流代码…

ESCTF-OSINT赛题WP

这你做不出来?check ESCTF{湖北大学_嘉会园食堂} 这个识图可以发现是 淡水渔人码头 但是 osint 你要发现所有信息 聊天记录说国外 同时 提示给了美国 你综合搜索 美国 渔人码头 在美国旧金山的渔人码头&#xff08;英语&#xff1a;Fisherman’s Wharf&#xff09;是一个著名旅…

ubuntu虚拟机扩展容量后,无效,其实还需要分配

参考这位大佬&#xff1a;https://www.cnblogs.com/learningendless/p/17718003.html 如果直接使用磁盘调整大小会发现有钥匙 会被锁住&#xff0c;无法调整&#xff0c;按照大佬步骤做&#xff0c;亲测有效

浅谈关于Linux的学习

Linux的整个知识构架是&#xff1a; 1、基本指令 2、系统编程 3、网络编程 指令只是很基础的一部分&#xff0c;学习Linux更加重要的是其底层原理的知识&#xff0c;需要从基本的指令开始&#xff0c;逐级而上&#xff0c;次第往深处挖掘。最后构建起整个的知识体系。而不是仅…

docker容器虚拟化-4

文章目录 虚拟化网络单节点容器间通信不同节点容器间通信 虚拟化网络 Network Namespace 是 Linux 内核提供的功能&#xff0c;是实现网络虚拟化的重要功能&#xff0c;它能创建多个隔离的网络空间&#xff0c;它们有独自网络栈信息。不管是虚拟机还是容器&#xff0c;运行的时…

【大模型 数据增强】LLM2LLM:迭代学习 + 针对性增强 + 错误分析 + 合成数据生成 + 质量控制

LLM2LLM&#xff1a;迭代学习 针对性增强 错误分析 合成数据生成 质量控制 提出背景针对性和迭代性数据增强&#xff08;LLM2LLM&#xff09;步骤1&#xff1a;在数据集上训练步骤2&#xff1a;在数据集上评估步骤3&#xff1a;生成额外数据 算法流程医学领域数据增强&…