第一题
leetcode42:接雨水
public class 第一题01 {
public static int trap1(int[] height) {
int n = height.length;
int sum = 0;
int[] left = new int[n];
int[] right = new int[n];
left[0] = height[0];
for (int i = 1;i < n;i++){
left[i] = Math.max(left[i - 1],height[i]);
}
right[n - 1] = height[n - 1];
for(int i = n - 2;i >= 0;i--){
right[i] = Math.max(right[i + 1],height[i]);
}
for (int i = 1;i < n - 1;i++){
int min_height = Math.min(left[i],right[i]);
sum += min_height > height[i] ? min_height - height[i] : 0;
}
return sum;
}
public static int trap2(int[] height) {
int left_max = 0;
int right_max = 0;
int l = 0;
int r = height.length - 1;
int sum = 0;
while (l < r){
if (left_max > right_max){
sum += right_max > height[r] ? right_max - height[r] : 0;
right_max = Math.max(right_max,height[r]);
r--;
}else {
sum += left_max > height[l] ? left_max - height[l] : 0;
left_max = Math.max(left_max,height[l]);
l++;
}
}
return sum;
}
}
第二题
leetcode169:多数元素
1.超级水王问题:给你一个数组,出现次数大于数组长度的一半的元素称之为水王数,怎么能快速找到水王数?
内存限制:时间复杂度O(n),额外空间复杂度O(1)——也就是遍历数组的次数为有限次,申请的变量数为有限个
2.扩展:给定一个长度为N的数组arr,和一个大于1的正整数K,如果有哪些数出现的次数大于N/K,就返回这些数
要求:时间复杂度O(N) 额外空间复杂度O(K)
public class 第二题07 {
public static void main(String[] args) {
int[] arr = {1,2,3,1,2,3,1,2,1,2,1,2,1,3};
int res = waterKing(arr);
System.out.println(res);
List<Integer> list = getSuperWaterExtension(arr, 4);
System.out.println(list);
}
//1.超级水王问题
public static int waterKing(int[] arr){
int n = arr.length;
int cand = 0;
int hp = 0;
for (int i = 0;i < n;i++){
if (hp == 0){
cand = arr[i];
hp++;
}else {
if (cand == arr[i]){
hp++;
}else {
hp--;
}
}
}
if (hp == 0){
return -1;
}
int mid = n / 2;
int num = 0;
for (int i = 0;i < n;i++){
if (cand == arr[i]){
num++;
}
}
if (num > mid){
return cand;
}
return -1;
}
//2.扩展:给定一个长度为N的数组arr,和一个大于1的正整数K,如果有哪些数出现的次数大于N/K,就返回这些数(时间复杂度O(N) 额外空间复杂度O(K))
public static List<Integer> getSuperWaterExtension(int[] arr, int K){
HashMap<Integer, Integer> map = new HashMap<>();
int n = arr.length;
for (int i = 0;i < n;i++){
if (map.containsKey(arr[i])){
map.put(arr[i],map.get(arr[i]) + 1);
}else {
if (map.size() == K - 1){
allMapMinusOne(map);
}else {
map.put(arr[i],1);
}
}
}
HashMap<Integer,Integer> res = getReals(arr,map);
ArrayList<Integer> ans = new ArrayList<>();
int M = n / K;
for (Integer num : res.keySet()){
if (res.get(num) > M){
ans.add(num);
}
}
return ans;
}
private static HashMap<Integer, Integer> getReals(int[] arr, HashMap<Integer, Integer> map) {
HashMap<Integer, Integer> res = new HashMap<>();
for (int num : arr){
if (map.containsKey(num)){
res.put(num,res.getOrDefault(num,0) + 1);
}
}
return res;
}
private static void allMapMinusOne(HashMap<Integer, Integer> map) {
ArrayList<Integer> list = new ArrayList<>();
for (Integer num : map.keySet()){
Integer count = map.get(num) - 1;
if (count == 0){
list.add(num);
}else {
map.put(num,count);
}
}
for (Integer num : list){
map.remove(num);
}
}
}
第三题
leetcode1000. 合并石头的最低成本
思路:暴力递归——》记忆化搜索
package 高频算法题82.大厂面试算法题.第七天;
public class 第三题07 {
//暴力递归
public static int mergeStones1(int[] stones, int k) {
int n = stones.length;
if ((n - 1) % (k - 1) > 0){
return -1;
}
int[] preSum = new int[n + 1];
for (int i = 0;i < n;i++){
preSum[i + 1] = preSum[i] + stones[i];
}
return process1(stones,0,stones.length - 1,k,1,preSum);
}
// [L ... R]合并为part份的最小代价,如果无法完成,返回-1
// preSum[i]:[0 ... i-1]的前缀累加和
public static int process1(int[] arr,int L,int R,int K,int P,int[] preSum){
if (L == R){
return P == 1 ? 0 : -1;
}
if (P == 1){
int next = process1(arr,L,R,K,K,preSum);
if (next == -1){
return -1;
}else {
return next + preSum[R + 1] - preSum[L];
}
}else {
int ans = Integer.MAX_VALUE;
for (int i = L;i < R;i += K - 1){
int left = process1(arr,L,i,K,1,preSum);
int right = process1(arr,i + 1,R,K,P - 1,preSum);
if (left != -1 && right != -1){
ans = Math.min(ans,left + right);
}
}
return ans;
}
}
//记忆化搜索
public static int mergeStones2(int[] stones, int k) {
int n = stones.length;
if ((n - 1) % (k - 1) > 0){
return -1;
}
int[] preSum = new int[n + 1];
for (int i = 0;i < n;i++){
preSum[i + 1] = preSum[i] + stones[i];
}
int[][][] dp = new int[n][n][k - 1];
return process1(stones,0,stones.length - 1,k,1,preSum,dp);
}
public static int process1(int[] arr, int L, int R, int K, int P, int[] preSum, int[][][] dp){
if (dp[L][R][P] != 0){
return dp[L][R][P];
}
if (L == R){
return P == 1 ? 0 : -1;
}
if (P == 1){
int next = process1(arr,L,R,K,K,preSum, dp);
if (next == -1){
dp[L][R][P] = -1;
return dp[L][R][P];
}else {
dp[L][R][P] = next + preSum[R + 1] - preSum[L];
return dp[L][R][P];
}
}else {
int ans = Integer.MAX_VALUE;
for (int i = L;i < R;i += K - 1){
int left = process1(arr,L,i,K,1,preSum, dp);
int right = process1(arr,i + 1,R,K,P - 1,preSum, dp);
if (left != -1 && right != -1){
ans = Math.min(ans,left + right);
dp[L][R][P] = ans;
}else {
dp[L][R][P] = -1;
}
}
return dp[L][R][P];
}
}
}
第四题
leetcode:剑指 Offer II 017. 含有所有字符的最短字符串
public class 第五题07 {
public static String removeDuplicateLetters(String s) {
if (s == null || s.length() < 2){
return s;
}
int[] map = new int[256];
int n = s.length();
char[] str = s.toCharArray();
int ascii_min = 0;
for (int i = 0;i < n;i++){
map[str[i]]++;
}
for (int i = 0;i < n;i++){
ascii_min = str[ascii_min] > str[i] ? i : ascii_min;
map[str[i]]--;
if (map[str[i]] == 0){
break;
}
}
return String.valueOf(str[ascii_min]) + removeDuplicateLetters(s.substring(ascii_min + 1).replaceAll(String.valueOf(str[ascii_min]),""));
}
}
第六题
leetcode22:括号生成
public class 第六题07 {
public static void main(String[] args) {
boolean res = isValid("()");
System.out.println(res);
}
public static boolean isValid(String s) {
int n = s.length();
char[] str = s.toCharArray();
char[] stack = new char[n];
int index = 0;
for (int i = 0;i < n;i++){
if (str[i] == '('){
stack[index++] = ')';
}else if (str[i] == '{'){
stack[index++] = '}';
}else if (str[i] == '['){
stack[index++] = ']';
}else {
if (index <= 0 || stack[--index] != str[i]){
return false;
}
}
}
if (index > 0){
return false;
}
return true;
}
}
第七题
leetcode36:有效数独
public class 第七题07 {
public boolean isValidSudoku(char[][] board) {
boolean[][] row = new boolean[10][10];
boolean[][] col = new boolean[10][10];
boolean[][] box = new boolean[10][10];
for (int i = 0;i < 9;i++){
for (int j = 0;j < 9;j++){
if (board[i][j] != '.'){
int num = board[i][j] - '0';
int b = 3 * (i / 3) + (j / 3);
if (row[i][num] || col[j][num] || box[b][num]){
return false;
}
row[i][num] = true;
col[j][num] = true;
box[b][num] = true;
}
}
}
return true;
}
}