1、合并区间
将数组按照数组第一个值大小进行排序,然后遍历时比较临近数组的首尾数字 引入list
,用来存储结果
public static int[][] merge(int[][] intervals) {
List<int[]> lists = new ArrayList<int[]>();
Arrays.sort(intervals, new Comparator<int[]>() { //排序
@Override
public int compare(int[] o1, int[] o2) {
return Integer.compare(o1[0], o2[0]);
}
}); 表达式写法 Arrays.sort(intervals,(a,b)-> a[0] - b[0]);
for (int i = 0; i < intervals.length; i++) {
int left = intervals[i][0];
int right = intervals[i][1];
if (lists.size() == 0 || lists.get(lists.size() - 1)[1] < left) {
lists.add(new int[]{left, right}); //如果第一个,且遍历较大数字
} else {
//取当前遍历数字和上一个存储的数字最大值。
lists.get(lists.size() - 1)[1] = Math.max(lists.get(lists.size() - 1)[1], right);
}
}
return lists.toArray(new int[lists.size()][]);
}
2、轮转数组
模拟运算
nums = "----->-->"; k =3
result = "-->----->";
reverse "----->-->" we can get "<--<-----"
reverse "<--" we can get "--><-----"
reverse "<-----" we can get "-->----->"
this visualization help me figure it out :)
实际运算
public void rotate(int[] nums, int k) {
int len = nums.length;
k = k % nums.length;
reverse(nums, 0, len - 1);
reverse(nums, 0, k-1);
reverse(nums, k, len - 1);
}
public void reverse(int[] nums, int start, int end) {
while (start < end) {
int temp = nums[start];
nums[start] = nums[end];
nums[end] = temp;
start+=1;
end -= 1;
}
}
3、除自身以外数组的乘积
基础版
由于是算除自身以外数组的乘积,因此以当前遍历的为中心,算出当前数字的左右两边的乘积和,然后将左右两边的乘积进行相乘
class Solution {
public int[] productExceptSelf(int[] nums) {
int len = nums.length;
int[] answer = new int[nums.length];
int[] right = new int[len]; // 存储从当前位置右侧的所有元素的乘积
int[] left = new int[len]; // 存储从当前位置左侧的所有元素的乘积
int leftSum = 1;
int rightSum = 1;
left[0] = 1; // 初始化左侧乘积为1
for (int i = 1; i < len; i++) {
left[i] = left[i - 1] * nums[i - 1]; // 计算左侧乘积
}
right[len - 1] = 1; // 初始化右侧乘积为1
for (int i = len - 2; i >= 0; i--) {
right[i] = right[i + 1] * nums[i + 1]; // 计算右侧乘积
}
for (int i = 0; i < len; i++) {
answer[i] = left[i] * right[i]; // 将左侧乘积和右侧乘积相乘得到答案
}
return answer;
}
}
优化
由于在计算左右两边的乘积和时,会申请2n的空间,因此,在计算过程各种可以复用answer 由于没有右侧乘积,因此需要定义一个变量来记录右侧的乘积
public int[] productExceptSelf(int[] nums) {
int len = nums.length;
int[] answer = new int[len];
answer[0] = 1;
for (int i = 1; i < len; i++) {
answer[i] = answer[i - 1] * nums[i-1];
}
int rightSum = 1; //右侧乘积之和
for (int i = len-1; i >= 0; i--) {
answer[i] = answer[i] * rightSum;
rightSum *= nums[i];
}
return answer;
}
其他
思想同二,不过更加简洁,但是由于fill操作更占时间,所以时间耗时更长,且for中难以理解记忆。
public int[] productExceptSelf(int[] nums) {
int n=nums.length;
int[] ans=new int[n];
Arrays.fill(ans,1);
int beforeSum=1;
int afterSum=1;
for(int i=0,j=n-1;i<n;i++,j--){
ans[i]*=beforeSum;
ans[j]*=afterSum;
beforeSum*=nums[i];
afterSum*=nums[j];
}
return ans;
}