目录

题目1:给定一个有序数组arr,代表坐落在X轴上的点,给定一个正数K,代表绳子的长度。返回绳子最多压中几个点?即使绳子边缘处盖住点也算盖住。

题目2:一个数组中只有俩个字符'G'和'B',可以让所有的G都放在左侧,所有的B都放在右侧。或者可以让所有的G都放在右侧,所有的B都放在左侧。但是只能在相邻字符之间进行交换操作,问返回至少需要交换几次。

题目3:(leetcode494)给定一个数组arr,你可以在每个数字之前决定+或者-,但是必须所有数字都参与。再给定一个数target,请问最后算出target的方法数是多少。

题目4:现有司机M人,调度中心会将所有司机平分给A、B俩个区域。第i个司机去A可得到收入为income[i][0],第i个司机去B可得到收入为income[i][2],那么返回所有调度方案中能使所有司机总收入最高的方案,是多少钱。

题目5:HashMap实现setAll的功能。

题目6:(leetcode3)求一个字符串中,最长无重复字符子串长度

题目7:给定一个数组arr,代表每个人的能力值。在给定一个非负数k,如果俩个人能力差值正好为k,那么可以凑在一起比赛。一局比赛只有俩个人,返回最多可以同时有多少场比赛

题目8:(腾讯原题)给定一个正数数组arr,代表若干人的体重。再给定一个正数limit,表示所有船共同拥有的载重量。每艘船最多做俩人,且不能超过载重。想让所有的人同时过河,并且用最好的分配方法让船尽量少,返回最少的船数。

题目9:(leetcode53)返回一个数组中,子数组最大累加和

题目10:(leetcode135)分发糖果问题。

题目11:(leetcode97)字符串交错组成

题目12:如果一个节点X,它左树结构和右树结构完全一样。那么我们说以X为头的树是相等树,给定一颗二叉树的头节点head。返回head整棵树上有多少棵相等子树。

题目13:(leetcode72)编辑距离问题

题目14:(leetcode772)

题目15:(leetcode11)盛最多水的容器

题目16:(leetcode301)给你一个由若干括号和字母组成的字符串s,删除最小数量的无效括号,使得输入的字符串有效,返回所有可能的结果。

题目17:(leetcode300)最长递增子序列长度

题目18:定义何为step num?比如680,680+68+6=754,680的step num叫754。给定一个正数num,判断它是不是某个数的step num

题目19:(leetcode45)跳跃游戏Ⅱ

题目20:面试题 08.14. 布尔运算 - 力扣(LeetCode)

题目21:(leetcode517)超级洗衣机问题

题目22:约瑟夫环问题-剑指 Offer 62. 圆圈中最后剩下的数字 - 力扣(LeetCode)

题目23:(leetcode1643)第K条最小指令

题目24:(leetcode146)LRU

题目25:(leetcode42)一维接雨水

题目26:(leetcode407)二维接雨水


题目1:给定一个有序数组arr,代表坐落在X轴上的点,给定一个正数K,代表绳子的长度。返回绳子最多压中几个点?即使绳子边缘处盖住点也算盖住。

解题思路:用俩个指针L和R,判断它们的距离差,看情况R++或者L++。

时间复杂度是O(N)

    public static int maxPoint2(int[] arr, int L) {int left = 0;int right = 0;int N = arr.length;int max = 0;while (left < N) {while (right < N && arr[right] - arr[left] <= L) {right++;}max = Math.max(max, right - (left++));}return max;}

题目2:一个数组中只有俩个字符'G'和'B',可以让所有的G都放在左侧,所有的B都放在右侧。或者可以让所有的G都放在右侧,所有的B都放在左侧。但是只能在相邻字符之间进行交换操作,问返回至少需要交换几次。

解题思路:通过指针的方式去求解。

    public static int minSteps2(String s) {if (s == null || s.equals("")) {return 0;}char[] str = s.toCharArray();int step1 = 0;int step2 = 0;int gi = 0;int bi = 0;for (int i = 0; i < str.length; i++) {if (str[i] == 'G') { // 当前的G,去左边   方案1step1 += i - (gi++);} else {// 当前的B,去左边   方案2step2 += i - (bi++);}}return Math.min(step1, step2);}

题目3:(leetcode494)给定一个数组arr,你可以在每个数字之前决定+或者-,但是必须所有数字都参与。再给定一个数target,请问最后算出target的方法数是多少。

第一种方式暴力递归

    public static int findTargetSumWays1(int[] arr, int s) {return process1(arr, 0, s);}public static int process1(int[] arr, int index, int rest) {if (index == arr.length) { return rest == 0 ? 1 : 0;}return process1(arr, index + 1, rest - arr[index]) + process1(arr, index + 1, rest + arr[index]);}

第二种方式记忆化搜索(动态规划)

    public static int findTargetSumWays2(int[] arr, int s) {return process2(arr, 0, s, new HashMap<>());}//HashMap<Integer, HashMap<Integer, Integer>> dp// index + rest// index == 7 rest = 13   256// index == 7 rest = 35   17//{//  7 :  { 13 , 256}//    :  { 35 , 17}//}public static int process2(int[] arr, int index, int rest, HashMap<Integer, HashMap<Integer, Integer>> dp) {if (dp.containsKey(index) && dp.get(index).containsKey(rest)) {return dp.get(index).get(rest);}// 否则,没命中!int ans = 0;if (index == arr.length) {ans = rest == 0 ? 1 : 0;} else {ans = process2(arr, index + 1, rest - arr[index], dp) + process2(arr, index + 1, rest + arr[index], dp);}if (!dp.containsKey(index)) {dp.put(index, new HashMap<>());}dp.get(index).put(rest, ans);return ans;}

第三种方式动态规划(二维动态规划的空间压缩技巧)

理解业务过程

    // 优化点一 :// 你可以认为arr中都是非负数// 因为即便是arr中有负数,比如[3,-4,2]// 因为你能在每个数前面用+或者-号// 所以[3,-4,2]其实和[3,4,2]达成一样的效果// 那么我们就全把arr变成非负数,不会影响结果的// 优化点二 :// 如果arr都是非负数,并且所有数的累加和是sum// 那么如果target<sum,很明显没有任何方法可以达到target,可以直接返回0// 优化点三 :// arr内部的数组,不管怎么+和-,最终的结果都一定不会改变奇偶性// 所以,如果所有数的累加和是sum,// 并且与target的奇偶性不一样,没有任何方法可以达到target,可以直接返回0// 优化点四 :// 比如说给定一个数组, arr = [1, 2, 3, 4, 5] 并且 target = 3// 其中一个方案是 : +1 -2 +3 -4 +5 = 3// 该方案中取了正的集合为P = {1,3,5}// 该方案中取了负的集合为N = {2,4}// 所以任何一种方案,都一定有 sum(P) - sum(N) = target// 现在我们来处理一下这个等式,把左右两边都加上sum(P) + sum(N),那么就会变成如下:// sum(P) - sum(N) + sum(P) + sum(N) = target + sum(P) + sum(N)// 2 * sum(P) = target + 数组所有数的累加和// sum(P) = (target + 数组所有数的累加和) / 2// 也就是说,任何一个集合,只要累加和是(target + 数组所有数的累加和) / 2// 那么就一定对应一种target的方式// 也就是说,比如非负数组arr,target = 7, 而所有数累加和是11// 求有多少方法组成7,其实就是求有多少种达到累加和(7+11)/2=9的方法// 优化点五 :// 二维动态规划的空间压缩技巧public static int findTargetSumWays(int[] arr, int target) {int sum = 0;for (int n : arr) {sum += n;}return sum < target || ((target & 1) ^ (sum & 1)) != 0 ? 0 : subset2(arr, (target + sum) >> 1);}// 求非负数组nums有多少个子集,累加和是s// 二维动态规划// 不用空间压缩public static int subset1(int[] nums, int s) {if (s < 0) {return 0;}int n = nums.length;// dp[i][j] : nums前缀长度为i的所有子集,有多少累加和是j?int[][] dp = new int[n + 1][s + 1];// nums前缀长度为0的所有子集,有多少累加和是0?一个:空集dp[0][0] = 1;for (int i = 1; i <= n; i++) {for (int j = 0; j <= s; j++) {dp[i][j] = dp[i - 1][j];if (j - nums[i - 1] >= 0) {dp[i][j] += dp[i - 1][j - nums[i - 1]];}}}return dp[n][s];}// 不会空间压缩// 求非负数组nums有多少个子集,累加和是s// 二维动态规划// 用空间压缩:// 核心就是for循环里面的:for (int i = s; i >= n; i--) {// 为啥不枚举所有可能的累加和?只枚举 n...s 这些累加和?// 因为如果 i - n < 0,dp[i]怎么更新?和上一步的dp[i]一样!所以不用更新// 如果 i - n >= 0,dp[i]怎么更新?上一步的dp[i] + 上一步dp[i - n]的值,这才需要更新public static int subset2(int[] nums, int s) {if (s < 0) {return 0;}int[] dp = new int[s + 1];dp[0] = 1;for (int n : nums) {for (int i = s; i >= n; i--) {dp[i] += dp[i - n];}}return dp[s];}

题目4:现有司机M人,调度中心会将所有司机平分给A、B俩个区域。第i个司机去A可得到收入为income[i][0],第i个司机去B可得到收入为income[i][2],那么返回所有调度方案中能使所有司机总收入最高的方案,是多少钱。

    public static int maxMoney1(int[][] income) {if (income == null || income.length < 2 || (income.length & 1) != 0) {return 0;                  //(income.length & 1) != 0)  位运算,看其奇偶性}int N = income.length; // 司机数量一定是偶数,所以才能平分,A N /2 B N/2int M = N >> 1; // M = N / 2 要去A区域的人return process1(income, 0, M);}// index.....所有的司机,往A和B区域分配!// A区域还有rest个名额!// 返回把index...司机,分配完,并且最终A和B区域同样多的情况下,// index...这些司机,整体收入最大是多少!//    因为A区域能够推断出B区域。所以只需要一个区域变量就可以public static int process1(int[][] income, int index, int rest) {if (index == income.length) {return 0;}// 还剩下司机!if (income.length - index == rest) {return income[index][0] + process1(income, index + 1, rest - 1);}if (rest == 0) {return income[index][1] + process1(income, index + 1, rest);}// 当前司机,可以去A,或者去Bint p1 = income[index][0] + process1(income, index + 1, rest - 1);int p2 = income[index][1] + process1(income, index + 1, rest);return Math.max(p1, p2);}

题目5:HashMap实现setAll的功能。

import java.util.HashMap;public class Code05_SetAll {public static class MyValue<V> {public V value;public long time;public MyValue(V v, long t) {value = v;time = t;}}public static class MyHashMap<K, V> {private HashMap<K, MyValue<V>> map;private long time;  private MyValue<V> setAll;public MyHashMap() {map = new HashMap<>();time = 0;setAll = new MyValue<V>(null, -1);}public void put(K key, V value) {map.put(key, new MyValue<V>(value, time++));}public void setAll(V value) {setAll = new MyValue<V>(value, time++);}public V get(K key) {if (!map.containsKey(key)) {return null;}if (map.get(key).time > setAll.time) {return map.get(key).value;} else {return setAll.value;}}}
}

题目6:(leetcode3)求一个字符串中,最长无重复字符子串长度

暴力方法:俩个for循环即可实现。

我们是不是可以:每一个数字,都往左边推,去寻找目标S。取其MAX即可。

当子串、当子数组。。。。遇到这种问题的时候,就这么想~

从  0==》S    从 1 ==》 S

那么从整体上看,是不是从左到右的计算过程。那么我i位置上的内容,是不是可以依赖于i-1得出。

所以,此时根据此思想,可以想到加速的办法。

1)当前字符上次的位置

2)i-1位置往左推的距离

取MAX即可。又因为,我们只需要得到上一次的内容,所有只需要变量记录即可!!!

public class Code06_LongestSubstringWithoutRepeatingCharacters {public static int lengthOfLongestSubstring(String s) {if (s == null || s.equals("")) {return 0;}char[] str = s.toCharArray();// ASCII 只有 0~255// map[i] = v  i这个ascii码的字符,上次出现在V位置int[] map = new int[256];for (int i = 0; i < 256; i++) {map[i] = -1;}map[str[0]] = 0;int N = str.length;int ans = 1;       // 最少长度 1int pre = 1;       // 上一个位置,向左推了多长for (int i = 1; i < N; i++) {pre = Math.min(i - map[str[i]], pre + 1);ans = Math.max(ans, pre);map[str[i]] = i;}return ans;}}

题目7:给定一个数组arr,代表每个人的能力值。在给定一个非负数k,如果俩个人能力差值正好为k,那么可以凑在一起比赛。一局比赛只有俩个人,返回最多可以同时有多少场比赛

题意解析: [ 3 1 5 7 ]  k = 2   此时最多安排2场比赛  1 3  和 5 7

此时根据题意:可以想到一个暴力求解的方法,我们对其进行全排列,然后规定 0 1 比赛 2 3 比赛,那么最终答案一定在全排列中。

    // 时间复杂度O(N*logN)public static int maxPairNum2(int[] arr, int k) {if (k < 0 || arr == null || arr.length < 2) {return 0;}Arrays.sort(arr);int ans = 0;int N = arr.length;int L = 0;int R = 0;boolean[] usedR = new boolean[N];while (L < N && R < N) {if (usedR[L]) {L++;} else if (L >= R) { //只剩一人时  依据题意 L == R 也没事R++;} else { // 不止一个数,而且都没用过!int distance = arr[R] - arr[L];if (distance == k) {ans++;usedR[R++] = true;L++;} else if (distance < k) {R++;} else {L++;}}}return ans;}

题目8:(腾讯原题)给定一个正数数组arr,代表若干人的体重。再给定一个正数limit,表示所有船共同拥有的载重量。每艘船最多做俩人,且不能超过载重。想让所有的人同时过河,并且用最好的分配方法让船尽量少,返回最少的船数。

题意解析:[ 1 1 1 5 5 5 5 9 9 9]  limit = 10                   19   19   19   55  55       最少5艘船

整体的思路是一个贪心。。。。

    public static int numRescueBoats2(int[] people, int limit) {Arrays.sort(people);int ans = 0;int l = 0;int r = people.length - 1;int sum = 0;while (l <= r) {sum = l == r ? people[l] : people[l] + people[r];if (sum > limit) {r--;} else {l++;r--;}ans++;}return ans;}

题目9:(leetcode53)返回一个数组中,子数组最大累加和

当遇到 子串.....    子数组......   的时候,我们可以想到一个方法,就是  每个数都往左边找目标

    public static int maxSubArray2(int[] arr) {if (arr == null || arr.length == 0) {return 0;}// 上一步,dp的值// dp[0]int pre = arr[0];int max = arr[0];for (int i = 1; i < arr.length; i++) {pre = Math.max(arr[i], arr[i] + pre);max =  Math.max(max, pre);}return max;}

题目10:(leetcode135)分发糖果问题。

创建一个数组的时间复杂度是 O(N)

    // 这是原问题的优良解// 时间复杂度O(N),额外空间复杂度O(N)public static int candy1(int[] arr) {if (arr == null || arr.length == 0) {return 0;}int N = arr.length;int[] left = new int[N];for (int i = 1; i < N; i++) {if (arr[i - 1] < arr[i]) {left[i] = left[i - 1] + 1;}}int[] right = new int[N];for (int i = N - 2; i >= 0; i--) {if (arr[i] > arr[i + 1]) {right[i] = right[i + 1] + 1;}}int ans = 0;for (int i = 0; i < N; i++) {ans += Math.max(left[i], right[i]);}return ans + N;}

题目11:(leetcode97)字符串交错组成

样本对应模型

    public static boolean isInterleave(String s1, String s2, String s3) {if (s1 == null || s2 == null || s3 == null) {return false;}char[] str1 = s1.toCharArray();char[] str2 = s2.toCharArray();char[] str3 = s3.toCharArray();if (str3.length != str1.length + str2.length) {return false;}boolean[][] dp = new boolean[str1.length + 1][str2.length + 1];dp[0][0] = true;for (int i = 1; i <= str1.length; i++) {if (str1[i - 1] != str3[i - 1]) {break;}dp[i][0] = true;}for (int j = 1; j <= str2.length; j++) {if (str2[j - 1] != str3[j - 1]) {break;}dp[0][j] = true;}for (int i = 1; i <= str1.length; i++) {for (int j = 1; j <= str2.length; j++) {if ((str1[i - 1] == str3[i + j - 1] && dp[i - 1][j])||(str2[j - 1] == str3[i + j - 1] && dp[i][j - 1])) {dp[i][j] = true;}}}return dp[str1.length][str2.length];}

题目12:如果一个节点X,它左树结构和右树结构完全一样。那么我们说以X为头的树是相等树,给定一颗二叉树的头节点head。返回head整棵树上有多少棵相等子树。

    public static class Node {public int value;public Node left;public Node right;public Node(int v) {value = v;}}// 时间复杂度O(N * logN)public static int sameNumber1(Node head) {if (head == null) {return 0;}return sameNumber1(head.left) + sameNumber1(head.right) + (same(head.left, head.right) ? 1 : 0);}public static boolean same(Node h1, Node h2) {if (h1 == null ^ h2 == null) {return false;}if (h1 == null && h2 == null) {return true;}// 两个都不为空return h1.value == h2.value && same(h1.left, h2.left) && same(h1.right, h2.right);}

题目13:(leetcode72)编辑距离问题

样本对应模型,往往是根据字符串最后结尾来划分可能性~来做的~~~

    public static int minCost1(String s1, String s2, int ic, int dc, int rc) {if (s1 == null || s2 == null) {return 0;}char[] str1 = s1.toCharArray();char[] str2 = s2.toCharArray();int N = str1.length + 1;int M = str2.length + 1;int[][] dp = new int[N][M];// dp[0][0] = 0for (int i = 1; i < N; i++) {dp[i][0] = dc * i;}for (int j = 1; j < M; j++) {dp[0][j] = ic * j;}for (int i = 1; i < N; i++) {for (int j = 1; j < M; j++) {dp[i][j] = dp[i - 1][j - 1] + (str1[i - 1] == str2[j - 1] ? 0 : rc);dp[i][j] = Math.min(dp[i][j], dp[i][j - 1] + ic);dp[i][j] = Math.min(dp[i][j], dp[i - 1][j] + dc);}}return dp[N - 1][M - 1];}

题目14:(leetcode772)

给定一个字符串str,str表示一个公式,公式里可能有整数、加减乘除符号和左右括号,返回公式的计算结果,难点在于括号可能嵌套很多层

import java.util.LinkedList;// 本题测试链接 : https://leetcode.com/problems/basic-calculator-iii/
public class Code04_ExpressionCompute {public static int calculate(String str) {return f(str.toCharArray(), 0)[0];}// 请从str[i...]往下算,遇到字符串终止位置或者右括号,就停止// 返回两个值,长度为2的数组// 0) 负责的这一段的结果是多少// 1) 负责的这一段计算到了哪个位置public static int[] f(char[] str, int i) {LinkedList<String> que = new LinkedList<String>();int cur = 0;int[] bra = null;// 从i出发,开始撸串while (i < str.length && str[i] != ')') {if (str[i] >= '0' && str[i] <= '9') {cur = cur * 10 + str[i++] - '0';} else if (str[i] != '(') { // 遇到的是运算符号addNum(que, cur);que.addLast(String.valueOf(str[i++]));cur = 0;} else { // 遇到左括号了bra = f(str, i + 1);cur = bra[0];i = bra[1] + 1;}}addNum(que, cur);return new int[] { getNum(que), i };}public static void addNum(LinkedList<String> que, int num) {if (!que.isEmpty()) {int cur = 0;String top = que.pollLast();if (top.equals("+") || top.equals("-")) {que.addLast(top);} else {cur = Integer.valueOf(que.pollLast());num = top.equals("*") ? (cur * num) : (cur / num);}}que.addLast(String.valueOf(num));}public static int getNum(LinkedList<String> que) {int res = 0;boolean add = true;String cur = null;int num = 0;while (!que.isEmpty()) {cur = que.pollFirst();if (cur.equals("+")) {add = true;} else if (cur.equals("-")) {add = false;} else {num = Integer.valueOf(cur);res += add ? num : (-num);}}return res;}}

题目15:(leetcode11)盛最多水的容器

    public static int maxArea2(int[] h) {int max = 0;int l = 0;int r = h.length - 1;while (l < r) {max = Math.max(max, Math.min(h[l], h[r]) * (r - l));if (h[l] > h[r]) {r--;} else {l++;}}return max;}

题目16:(leetcode301)给你一个由若干括号和字母组成的字符串s,删除最小数量的无效括号,使得输入的字符串有效,返回所有可能的结果。

import java.util.ArrayList;
import java.util.List;// 测试链接 : https://leetcode.com/problems/remove-invalid-parentheses/
public class Code06_RemoveInvalidParentheses {// 来自leetcode投票第一的答案,实现非常好,我们来赏析一下public static List<String> removeInvalidParentheses(String s) {List<String> ans = new ArrayList<>();remove(s, ans, 0, 0, new char[] { '(', ')' });return ans;}// modifyIndex <= checkIndex// 只查s[checkIndex....]的部分,因为之前的一定已经调整对了// 但是之前的部分是怎么调整对的,调整到了哪?就是modifyIndex// 比如:// ( ( ) ( ) ) ) ...// 0 1 2 3 4 5 6// 一开始当然checkIndex = 0,modifyIndex = 0// 当查到6的时候,发现不对了,// 然后可以去掉2位置、4位置的 ),都可以// 如果去掉2位置的 ), 那么下一步就是// ( ( ( ) ) ) ...// 0 1 2 3 4 5 6// checkIndex = 6 ,modifyIndex = 2// 如果去掉4位置的 ), 那么下一步就是// ( ( ) ( ) ) ...// 0 1 2 3 4 5 6// checkIndex = 6 ,modifyIndex = 4// 也就是说,// checkIndex和modifyIndex,分别表示查的开始 和 调的开始,之前的都不用管了  par  (  )public static void remove(String s, List<String> ans, int checkIndex, int deleteIndex, char[] par) {for (int count = 0, i = checkIndex; i < s.length(); i++) {if (s.charAt(i) == par[0]) {count++;}if (s.charAt(i) == par[1]) {count--;}// i check计数<0的第一个位置if (count < 0) {for (int j = deleteIndex; j <= i; ++j) {// 比如if (s.charAt(j) == par[1] && (j == deleteIndex || s.charAt(j - 1) != par[1])) {remove(s.substring(0, j) + s.substring(j + 1, s.length()),ans, i, j, par);}}return;  //删除第一个不合法的。 直接return}}String reversed = new StringBuilder(s).reverse().toString();if (par[0] == '(') {remove(reversed, ans, 0, 0, new char[] { ')', '(' });} else {ans.add(reversed);}}}

题目17:(leetcode300)最长递增子序列长度

class Solution {public int lengthOfLIS(int[] nums) {if (nums.length == 0) {return 0;}int[] dp = new int[nums.length];dp[0] = 1;int maxans = 1;for (int i = 1; i < nums.length; i++) {dp[i] = 1;for (int j = 0; j < i; j++) {if (nums[i] > nums[j]) {dp[i] = Math.max(dp[i], dp[j] + 1);}}maxans = Math.max(maxans, dp[i]);}return maxans;}
}

public class Code07_LIS {public static int lengthOfLIS(int[] arr) {if (arr == null || arr.length == 0) {return 0;}int[] ends = new int[arr.length];ends[0] = arr[0];int right = 0;int l = 0;int r = 0;int m = 0;int max = 1;for (int i = 1; i < arr.length; i++) {l = 0;r = right;while (l <= r) {m = (l + r) / 2;if (arr[i] > ends[m]) {l = m + 1;} else {r = m - 1;}}right = Math.max(right, l);ends[l] = arr[i];max = Math.max(max, l + 1);}return max;}
}

题目18:定义何为step num?比如680,680+68+6=754,680的step num叫754。给定一个正数num,判断它是不是某个数的step num

题目解析:二分法

    public static boolean isStepSum(int stepSum) {int L = 0;int R = stepSum;int M = 0;int cur = 0;while (L <= R) {M = L + ((R - L) >> 1);cur = stepSum(M);if (cur == stepSum) {return true;} else if (cur < stepSum) {L = M + 1;} else {R = M - 1;}}return false;}public static int stepSum(int num) {int sum = 0;while (num != 0) {sum += num;num /= 10;}return sum;}

题目19:(leetcode45)跳跃游戏Ⅱ

题目解析如下:

public class Code09_JumpGame {public static int jump(int[] arr) {if (arr == null || arr.length == 0) {return 0;}int step = 0;int cur = 0;int next = 0;for (int i = 0; i < arr.length; i++) {if (cur < i) {step++;cur = next;}next = Math.max(next, i + arr[i]);}return step;}}

题目20:面试题 08.14. 布尔运算 - 力扣(LeetCode)

题目解析如下:

class Solution {public static int countEval(String express, int desired) {if (express == null || express.equals("")) {return 0;}char[] exp = express.toCharArray();int N = exp.length;Info[][] dp = new Info[N][N];Info allInfo = func(exp, 0, exp.length - 1, dp);return desired == 1 ? allInfo.t : allInfo.f;}public static class Info {public int t;   //为true的方法数public int f;   //为false的方法数public Info(int tr, int fa) {t = tr;f = fa;}}// 限制:// L...R上,一定有奇数个字符// L位置的字符和R位置的字符,非0即1,不能是逻辑符号!// 返回str[L...R]这一段,为true的方法数,和false的方法数public static Info func(char[] str, int L, int R, Info[][] dp) {if (dp[L][R] != null) {return dp[L][R];}int t = 0;int f = 0;if (L == R) {t = str[L] == '1' ? 1 : 0;f = str[L] == '0' ? 1 : 0;} else { // L..R >=3// 每一个种逻辑符号,split枚举的东西// 都去试试最后结合for (int split = L + 1; split < R; split += 2) {Info leftInfo = func(str, L, split - 1, dp);Info rightInfo = func(str, split + 1, R, dp);int a = leftInfo.t;int b = leftInfo.f;int c = rightInfo.t;int d = rightInfo.f;switch (str[split]) {case '&':t += a * c;f += b * c + b * d + a * d;break;case '|':t += a * c + a * d + b * c;f += b * d;break;case '^':t += a * d + b * c;f += a * c + b * d;break;}}}dp[L][R] = new Info(t, f);return dp[L][R];}
}

题目21:(leetcode517)超级洗衣机问题

题目解析如下:

    public static int findMinMoves(int[] arr) {if (arr == null || arr.length == 0) {return 0;}int size = arr.length;int sum = 0;for (int i = 0; i < size; i++) {sum += arr[i];}if (sum % size != 0) {return -1;}int avg = sum / size;int leftSum = 0;int ans = 0;for (int i = 0; i < arr.length; i++) {int leftRest = leftSum - i * avg;int rightRest = (sum - leftSum - arr[i]) - (size - i - 1) * avg;if (leftRest < 0 && rightRest < 0) {ans = Math.max(ans, Math.abs(leftRest) + Math.abs(rightRest));} else {ans = Math.max(ans, Math.max(Math.abs(leftRest), Math.abs(rightRest)));}leftSum += arr[i];}return ans;}

题目22:约瑟夫环问题-剑指 Offer 62. 圆圈中最后剩下的数字 - 力扣(LeetCode)

题目解析如下:

公式:  前 = (后 + m - 1) % i + 1 ;

    // 提交直接通过// 给定的编号是0~n-1的情况下,数到m就杀// 返回谁会活?public int lastRemaining1(int n, int m) {return getLive(n, m) - 1;}// 课上题目的设定是,给定的编号是1~n的情况下,数到m就杀// 返回谁会活?public static int getLive(int n, int m) {if (n == 1) {return 1;}//公式:前 = (后 + m - 1) % i + 1 ;return (getLive(n - 1, m) + m - 1) % n + 1;}
class Solution {public int lastRemaining(int n, int m) {int ans = 1;int r = 1;while (r <= n) {ans = (ans + m - 1) % (r++) + 1;}return ans - 1;}
}

题目23:(leetcode1643)第K条最小指令

    // 二分的方法public static int kthSmallest2(int[][] matrix, int k) {int N = matrix.length;int M = matrix[0].length;int left = matrix[0][0];int right = matrix[N - 1][M - 1];int ans = 0;while (left <= right) {int mid = left + ((right - left) >> 1);// <=mid 有几个 <= mid 在矩阵中真实出现的数,谁最接近midInfo info = noMoreNum(matrix, mid);if (info.num < k) {left = mid + 1;} else {ans = info.near;right = mid - 1;}}return ans;}public static class Info {public int near;public int num;public Info(int n1, int n2) {near = n1;num = n2;}}public static Info noMoreNum(int[][] matrix, int value) {int near = Integer.MIN_VALUE;int num = 0;int N = matrix.length;int M = matrix[0].length;int row = 0;int col = M - 1;while (row < N && col >= 0) {if (matrix[row][col] <= value) {near = Math.max(near, matrix[row][col]);num += col + 1;row++;} else {col--;}}return new Info(near, num);}

题目24:(leetcode146)LRU

 题目解析:


import java.util.HashMap;public class LRUCache {public LRUCache(int capacity) {cache = new MyCache<>(capacity);}private MyCache<Integer, Integer> cache;public int get(int key) {Integer ans = cache.get(key);return ans == null ? -1 : ans;}public void put(int key, int value) {cache.set(key, value);}public static class Node<K, V> {public K key;public V value;public Node<K, V> last;public Node<K, V> next;public Node(K key, V value) {this.key = key;this.value = value;}}public static class NodeDoubleLinkedList<K, V> {private Node<K, V> head;private Node<K, V> tail;public NodeDoubleLinkedList() {head = null;tail = null;}// 现在来了一个新的node,请挂到尾巴上去public void addNode(Node<K, V> newNode) {if (newNode == null) {return;}if (head == null) {head = newNode;tail = newNode;} else {tail.next = newNode;newNode.last = tail;tail = newNode;}}// node 入参,一定保证!node在双向链表里!// node原始的位置,左右重新连好,然后把node分离出来// 挂到整个链表的尾巴上public void moveNodeToTail(Node<K, V> node) {if (tail == node) {return;}if (head == node) {head = node.next;head.last = null;} else {node.last.next = node.next;node.next.last = node.last;}node.last = tail;node.next = null;tail.next = node;tail = node;}public Node<K, V> removeHead() {if (head == null) {return null;}Node<K, V> res = head;if (head == tail) {head = null;tail = null;} else {head = res.next;res.next = null;head.last = null;}return res;}}public static class MyCache<K, V> {private HashMap<K, Node<K, V>> keyNodeMap;private NodeDoubleLinkedList<K, V> nodeList;private final int capacity;public MyCache(int cap) {keyNodeMap = new HashMap<K, Node<K, V>>();nodeList = new NodeDoubleLinkedList<K, V>();capacity = cap;}public V get(K key) {if (keyNodeMap.containsKey(key)) {Node<K, V> res = keyNodeMap.get(key);nodeList.moveNodeToTail(res);return res.value;}return null;}// set(Key, Value)// 新增  更新value的操作public void set(K key, V value) {if (keyNodeMap.containsKey(key)) {Node<K, V> node = keyNodeMap.get(key);node.value = value;nodeList.moveNodeToTail(node);} else { // 新增!Node<K, V> newNode = new Node<K, V>(key, value);keyNodeMap.put(key, newNode);nodeList.addNode(newNode);if (keyNodeMap.size() == capacity + 1) {removeMostUnusedCache();}}}private void removeMostUnusedCache() {Node<K, V> removeNode = nodeList.removeHead();keyNodeMap.remove(removeNode.key);}}}

题目25:(leetcode42)一维接雨水

题意解析如下:

下面开始最优解

package Didi.class03;// 本题测试链接 : https://leetcode.com/problems/trapping-rain-water/
public class Code05_TrappingRainWater {public static int trap(int[] arr) {if (arr == null || arr.length < 2) {return 0;}int N = arr.length;int L = 1;int leftMax = arr[0];int R = N - 2;int rightMax = arr[N - 1];int water = 0;while (L <= R) {if (leftMax <= rightMax) {water += Math.max(0, leftMax - arr[L]);leftMax = Math.max(leftMax, arr[L++]);} else {water += Math.max(0, rightMax - arr[R]);rightMax = Math.max(rightMax, arr[R--]);}}return water;}}

题目26:(leetcode407)二维接雨水

import java.util.PriorityQueue;public class Solution {public static class Node {public int value;public int row;public int col;public Node(int v, int r, int c) {value = v;row = r;col = c;}}public static int trapRainWater(int[][] heightMap) {if (heightMap == null || heightMap.length == 0 || heightMap[0] == null || heightMap[0].length == 0) {return 0;}int N = heightMap.length;int M = heightMap[0].length;boolean[][] isEnter = new boolean[N][M];PriorityQueue<Node> heap = new PriorityQueue<>((a, b) -> a.value - b.value);for (int col = 0; col < M - 1; col++) {isEnter[0][col] = true;heap.add(new Node(heightMap[0][col], 0, col));}for (int row = 0; row < N - 1; row++) {isEnter[row][M - 1] = true;heap.add(new Node(heightMap[row][M - 1], row, M - 1));}for (int col = M - 1; col > 0; col--) {isEnter[N - 1][col] = true;heap.add(new Node(heightMap[N - 1][col], N - 1, col));}for (int row = N - 1; row > 0; row--) {isEnter[row][0] = true;heap.add(new Node(heightMap[row][0], row, 0));}int water = 0;int max = 0;while (!heap.isEmpty()) {Node cur = heap.poll();max = Math.max(max, cur.value);int r = cur.row;int c = cur.col;//   上if (r > 0 && !isEnter[r - 1][c]) {water += Math.max(0, max - heightMap[r - 1][c]);isEnter[r - 1][c] = true;heap.add(new Node(heightMap[r - 1][c], r - 1, c));}//  下if (r < N - 1 && !isEnter[r + 1][c]) {water += Math.max(0, max - heightMap[r + 1][c]);isEnter[r + 1][c] = true;heap.add(new Node(heightMap[r + 1][c], r + 1, c));}// 左if (c > 0 && !isEnter[r][c - 1]) {water += Math.max(0, max - heightMap[r][c - 1]);isEnter[r][c - 1] = true;heap.add(new Node(heightMap[r][c - 1], r, c - 1));}// 右if (c < M - 1 && !isEnter[r][c + 1]) {water += Math.max(0, max - heightMap[r][c + 1]);isEnter[r][c + 1] = true;heap.add(new Node(heightMap[r][c + 1], r, c + 1));}}return water;}}

leetcode(494/3/53/135/97/72/772/11/301/300/45/517/1643/146/42/407)面试题08.14~剑指offer62相关推荐

  1. 【LeetCode】《剑指Offer》第Ⅴ篇⊰⊰⊰ 39 - 47题

    [LeetCode]<剑指Offer>第Ⅴ篇⊰⊰⊰ 39 - 47题 文章目录 [LeetCode]<剑指Offer>第Ⅴ篇⊰⊰⊰ 39 - 47题 39. 数组中出现次数超过 ...

  2. leetcode剑指offer4

    leetcode剑指offer4 剑指 Offer 19. 正则表达式匹配 剑指 Offer 20. 表示数值的字符串 剑指 Offer 21. 调整数组顺序使奇数位于偶数前面 剑指 Offer 22 ...

  3. leetcode hot 100(刷题篇9)(301/45/517/407/offer62/MST08.14/7/9/14/16)

    目录 1.leetcode301删除无效的括号 2.leetcode45跳跃游戏 II 3.leetcode517超级洗衣机 4.leetcode407接雨水 II 5.面试题 08.14. 布尔运算 ...

  4. 【LeetCode】剑指 Offer 53 - I. 在排序数组中查找数字 I

    [LeetCode]剑指 Offer 53 - I. 在排序数组中查找数字 I 文章目录 [LeetCode]剑指 Offer 53 - I. 在排序数组中查找数字 I 一.二分法 总结 一.二分法 ...

  5. LeetCode—494. 目标和(Target Sum)——分析及代码(Java)

    LeetCode-494. 目标和[Target Sum]--分析及代码[Java] 一.题目 二.分析及代码 1. 动态规划 (1)思路 (2)代码 (3)结果 2. 动态规划+节省空间 (1)思路 ...

  6. 二刷剑指Offer:剑指Offer+LeetCode(全53题)

    文章目录 剑指Offer刷题 67. 剪绳子(贪心算法) 66. 机器人的运动范围(dfs) 65. 矩阵中的路径(回溯算法) 64. 滑动窗口的最大值(双端队列) 63. 数据流中的中位数 62. ...

  7. 【剑指offer】【leetcode精选题集】【Java】剑指offer题解合集 更新中

    Leetcode题集 [剑指offer][JAVA]面试题第[03]题[数组中的重复数字][HashSet] [剑指offer][JAVA]面试题第[04]题[二维数中的查找][数组] [剑指offe ...

  8. leetcode 打印_剑指 Offer 总结 - leetcode 剑指offer系列

    剑指 Offer 系列完结撒花!! 本篇文章是对整个系列的精华总结, 对系列的每篇文章进行了分类, 并用一句话概括每道题的思路, 方便大家理解和记忆, 当然也包含原文完整链接供大家参考 总的来说, 写 ...

  9. C#LeetCode刷题-剑指Offer

    本文由 比特飞 原创发布,欢迎大家踊跃转载. 转载请注明本文地址:C#LeetCode刷题-剑指Offer | .Net中文网. C#LEETCODE刷题概述 概述 所有LeetCode剑指Offer ...

最新文章

  1. poj1511(SPFA算法)
  2. 在巴塞罗那,华为挥别昨日 | MWC 2019
  3. mysql一个死锁分析
  4. webform 分页、组合查询综合使用
  5. Python-OpenCV 处理视频(三)(四)(五): 标记运动轨迹 运动检测 运动方向判断
  6. 谈谈java面向对象思想_对于Java面向对象思想的理解
  7. JavaWeb 命名规则
  8. LinkedList源码详解
  9. 详细地图_一目了然:蒙城学区划分详细地图
  10. 【经验分享】在研究中,你是否踩过这些工程的“坑”?
  11. MyBatis使用in进行列表中数据的批量删除
  12. 【5分钟paper】基于近似动态规划的学习、规划和反应的集成架构
  13. matlab对语音信号预加重处理,语音信号的预加重处理和加窗处理
  14. 三、Snapman多人协作电子表格之——软件的基本功能
  15. 2021-10-21python中spilt函数的学习
  16. 【SVAC1】SVAC1.0场解码相关分析
  17. 使用chrome浏览器打开微信页面配置方式
  18. 考虑储能削峰填谷的含DG配电网可靠性评估
  19. 送给八年以前两年以后的自己
  20. 电路设计基础--三极管驱动直流电机电路

热门文章

  1. 用Python实现栈---1顺序表:牛客题解 AB1 【模板】栈
  2. 如何使用IAR提供的模板文件template.eww 在CC2652R平台开发
  3. tinymce 一键排版功能 tpLayout
  4. 远程连接SQL Server (以sql server2008 Express为例)
  5. 【Ctfer训练计划】——(一)
  6. 又一行业盛会落地深圳!世链“FAF世界区块链3000人大会”全网热度领先
  7. 展会预告 | 我们相约宁波——2019世界数字经济大会
  8. 你为什么还在坚持玩《我的世界》?如何搭建《我的世界》服务器?
  9. mosquito php,linux下实施mosquito
  10. 解决7牛上传图片错误:error: file exists