8/12
4 移动0(将所有非零元素移动到前面,0元素移动到后面,且顺序不改变)
思路:
1 双指针遍历,指针1之前表示以整理好的数组,指针2指向待排序数字,如果指针2为非0元素,则和指针1的元素交换
2 按顺序记录所有非0元素的值,后面全部赋值为0,双指针,指针1指向已排序好的非0元素,指针2指向未排序的非0数组,指针2指向非0元素,则复制给指针1的元素交换。
5 乘最多水的容器(坐标轴y作为壁,问如何与x轴一起装下最多的水)
思路:
1 遍历穷举o(n^2)超时。如何剪枝减少时间复杂度。面积=长*宽,数组元素个数确定,我们可以想到将长(即x)拉到最大,之后向着两端减少改变高(哪边的高小,哪边缩进),进行一次遍历得到最大值
核心代码:
导入Math包,用到Math.min()
6 三数之和(在数组中选出三个数,若这三个数的和等于0,则将这三个数组成的数组加入Arraylist中,且不能包括重复的三元组)
思路:
三个数之和=0,直接想到穷举o(n^3),要不重复,因此可以先给数组进行排序,在旁段(1,2,3)这三个位置的数字是否和之前一样,一样则直接跳到下一个元素,保证不重复。但是o(n^3)时间复杂度太大。如何进行优化,如果我们已经穷举了两个数,那么只有唯一的c,使得a+b+c=0,因此从最大的地方开始穷举c,并保证其下标不小于b,且c的位置得以保存,是的这两轮穷举并到一轮。
核心代码:
List<List<Integer>> ans = new ArrayList<>();
List<Integer> list = new ArrayList<Integer>();
int target = -nums[i];
int k = n-1;
for(int j=i+1; j<n-1; j++){
if(j>i+1 && nums[j]==nums[j-1]){
continue;
}
while(j<k && nums[j] +nums[k] > target){
--k;
}
if(j == k){
break;
}
if(nums[j] + nums[k] == target){
List<Integer> list = new ArrayList<Integer>();
list.add(nums[i]);
list.add(nums[j]);
list.add(nums[k]);
ans.add(list);
}
}
7 接雨水,数组之为实心柱子的高度,问数组这些柱子能接住多少雨水
思路:
这边是问一共能接住多少雨水。因此可以一个位置一个位置的算这边能接住多少雨水,加起来就是一共能接住多少雨水,发现,一个位置接住的雨水数=min(这个位置柱子左边的最高位置, 这个柱子右边的最高值)-这个柱子的高度。这样其空间复杂度为o(n)在算法中是可以接受的。
但是如何降低空间复杂度。我们使用动态规划的方法计算其左边的最大值和右边的最大值,left[i] = max(height[i],left[i-1]),因此这边可以维护leftmax和rightmax两个数来零时存储左边的最大值和右边的最大值。并初始化两个指针left和right。
当leftmax<rightmax 位置left的rightmax不确实,但是其leftmax是确定的,且比rightmax来的小,因此其面积就为leftmax-height[left],++left。
反之类似。
核心代码:
import java.lang.Math;
for(int i=1; i<n; i++){
left[i] = Math.max(left[i-1], height[i-1]);
}