题目一
- 给定一个数组代表一个容器,比如[3,1,2,4],
代表0位置是一个宽度为1,高度为3的直方图。
代表1位置是一个宽度为1,高度为1的直方图。
代表2位置是一个宽度为1,高度为2的直方图。
代表3位置是一个宽度为1,高度为4的直方图。
所有直方图的底部都在一条水平线上,且紧靠着。
把这个图想象成一个容器,这个容器可以装3格的水。
给定一个没有负数的数组arr,返回能装几格水. - 题意理解
- 解法一
public static int getWater(int[] arr){
if(arr == null || arr.length < 3){
return 0;
}
int value = 0;
int leftMax = arr[0];
int rightMax = arr[arr.length - 1];
int l = 1;
int r = arr.length - 2;
while (l <= r){
if(leftMax <= rightMax){
value += Math.max(0, leftMax - arr[l]);
leftMax = Math.max(leftMax, arr[l]);
l++;
}else {
value += Math.max(0, rightMax - arr[r]);
rightMax = Math.max(rightMax, arr[r]);
r--;
}
}
return value;
}
- 解法二:引入辅助数组
arr = [3, 2, 4, 5, 4, 3, 1]
tmp1 = [3, 3, 4, 5, 5, 5, 5]
tmp2 = [5, 5, 5, 5, 4, 3, 1]
arr为原数组,tmp1记录[0, index]的最大值,tmp2记录[index,N - 1]的最大值
注意这里-2的原因是只记录非两端的数组的value
public static int getWater2(int[] arr){
if(arr == null || arr.length < 3){
return 0;
}
int n = arr.length - 2;
int[] leftMaxs = new int[n];
leftMaxs[0] = arr[0];
for (int i = 1; i < n; i++) {
leftMaxs[i] = Math.max(leftMaxs[i - 1], arr[i]);
}
int[] rightMaxs = new int[n];
rightMaxs[n - 1] = arr[n + 1];
for (int i = n - 2; i >= 0; i--){
rightMaxs[i] = Math.max(rightMaxs[i + 1], arr[i + 2]);
}
int value = 0;
for (int i = 1; i <= n; i++) {
value += Math.max(0, Math.min(leftMaxs[i - 1], rightMaxs[i - 1]) - arr[i]);
}
return value;
}
题目二
- 给定一个数组arr,返回所有子数组的累加和中,最大的累加和
- 题意理解
子数组是连续的
子数组:
[0, 0] [0, 1] [0, 2] [0, 3] … [0, N - 1]
[1, 1] [1, 2] [1, 3] … [1, N - 1]
[2, 2] [2, 3] … [2, N - 1]
…
注意这里的“最大累加和”
public static int maxSum(int[] arr){
int cur = 0;
int max = Integer.MIN_VALUE;
if(arr == null || arr.length == 0){
return 0;
}
for (int i = 0; i < arr.length; i++) {
cur += arr[i];
max = Math.max(cur, max);
//注意数组全为负数的情况
cur = cur < 0 ? 0 : cur;
}
return max;
}
- 注意
cur = cur < 0 ? 0 : cur;
验证时要考虑 全为正数,全为负数,有正有负的情况
arr = [-2, -3, -5, -1]的情况,最大累加和应该是-1,但由于都为负数时依次累加sum越来越小,cur不赋值为0时返回最大累加和为-2。
假设:
- 假设[L, R]是累加和最大的子数组
- [L, R]所有累加和最大的子数组中最长的
举例:
subarray = [...... , 0, 0, 3, 4, ......]
[L, R]为此数组
subarray = [...... , 3, 4, ......]
性质1:
[0, L - 1]位置的累加和一定是负数,不可能是0。
若[0, L - 1]为0会包含在累加和最大的子数组中。
若[0, L - 1]是正数则包含在累加和最大的子数组中。
性质2:
[L, Z]累加不可能为负。
从L索引出发的任何一个元素都不可能是负值
题目三
- 给定一个字符串str,和一个整数k,返回str向右循环右移k位后的结果
- str = “12345” ,k = 3
左半部分逆序"21",右半部分逆序"543",“21543"整体逆序"345 | 12”
public static void rotateWord(char[] chs){
if(chs == null || chs.length == 0){
return;
}
reverse(chs, 0, chs.length - 1);
}
public static void rotate1(char[] chs, int size){
if(chs == null || size <= 0 || size >= chs.length){
return ;
}
reverse(chs, 0, size - 1);
reverse(chs, size, chs.length - 1);
reverse(chs, 0, chs.length - 1);
for (int i = 0; i < chs.length; i++){
System.out.print(chs[i] + " ");
}
}
public static void reverse(char[] chs, int start, int end){
char tmp = 0;
while (start < end){
tmp = chs[start];
chs[start] = chs[end];
chs[end] = tmp;
start++;
end--;
}
}
题目四
生成窗口最大值数组
【题目】
有一个整型数组arr和一个大小为w的窗口从数组的最左边滑到最右边,窗口每次向右边滑一个
位置。
例如,数组为[4,3,5,4,3,3,6,7],窗口大小为3时:
[4 3 5] 4 3 3 6 7 窗口中最大值为5
4 [3 5 4] 3 3 6 7 窗口中最大值为5
4 3 [5 4 3] 3 6 7 窗口中最大值为5
4 3 5 [4 3 3] 6 7 窗口中最大值为4
4 3 5 4 [3 3 6] 7 窗口中最大值为6
4 3 5 4 3 [3 6 7] 窗口中最大值为7
如果数组长度为n,窗口大小为w,则一共产生n-w+1个窗口的最大值。
请实现一个函数。
输入:整型数组arr,窗口大小为w。
输出:一个长度为n-w+1的数组res,res[i]表示每一种窗口状态下的最大值。
以本题为例,结果应该返回{5,5,5,4,6,7}
- 想想一个字符串其实是个循环数组,可以循环右移。比如”abc”,向右循环右移一位,得到”cab”,向右循环右移两位,得到“bca”,向右循环右移三位,得到“abc”,给定两个字符串str1和str2,判断str2是不是由str1循环右移得到的。
- 如果str1 str2长度不等,无解。
生成str1 + str1
生成窗口最大值数组
【题目】
有一个整型数组arr和一个大小为w的窗口从数组的最左边滑到最右边,窗口每次向右边滑一个
位置。
例如,数组为[4,3,5,4,3,3,6,7],窗口大小为3时:
[4 3 5] 4 3 3 6 7 窗口中最大值为5
4 [3 5 4] 3 3 6 7 窗口中最大值为5
4 3 [5 4 3] 3 6 7 窗口中最大值为5
4 3 5 [4 3 3] 6 7 窗口中最大值为4
4 3 5 4 [3 3 6] 7 窗口中最大值为6
4 3 5 4 3 [3 6 7] 窗口中最大值为7
如果数组长度为n,窗口大小为w,则一共产生n-w+1个窗口的最大值。
请实现一个函数。
输入:整型数组arr,窗口大小为w。
输出:一个长度为n-w+1的数组res,res[i]表示每一种窗口状态下的最大值。
以本题为例,结果应该返回{5,5,5,4,6,7}