6. Merge Two Sorted Arrays :点击打开链接
class Solution {
/**
* @param A and B: sorted integer array A and B.
* @return: A new sorted integer array
*/
public int[] mergeSortedArray(int[] A, int[] B) {
if(A==null || B==null){
return null;
}
int[] result=new int[A.length+B.length];
int i=0,j=0,index=0;
while(i<A.length && j<B.length){ //两个数组都从头元素一次比较,哪个的当前元素大,result数组里就装哪个
if(A[i]<B[j]){
result[index++]=A[i++]; //result数组的索引和两数组之一的索引同步推进
}else{
result[index++]=B[j++];
}
}
while(i<A.length){ //当一个数组全部比较完,只剩下另一个数组的一些元素,也要全部转入result
result[index++]=A[i++];;
}
while(j<B.length){
result[index++]=B[j++];
}
return result;
}
}
64. Merge Sorted Array:点击打开链接
因为添加或减少一个元素数组整体平移:O(n)
因此添加或减少m个元素而平移:O(m*n),与题O(m+n)不符,因此不能用整体平移
class Solution {
/**
* @param A: sorted integer array A which has m elements,
* but size of A is m+n
* @param B: sorted integer array B which has n elements
* @return: void
*/
public void mergeSortedArray(int[] A, int m, int[] B, int n) { //这题要先理解题意,A有足够空间装所有A和B的元素
int i=m-1,j=n-1,lastIndex=m+n-1; //而且要merge B into A
while(i>=0 && j>=0){ //从后面开始,先放大的,倒着来
if(A[i]>B[j]){ //因为A和Bsorted array,所以不会存在没有地方放的情况
A[lastIndex--]=A[i--];
}else{
A[lastIndex--]=B[j--];
}
}
while(i>=0){
A[lastIndex--]=A[i--];
}
while(j>=0){
A[lastIndex--]=B[j--];
}
}
}
547.Intersection of Two Arrays:点击打开链接
public class Solution {
/**
* @param nums1 an integer array
* @param nums2 an integer array
* @return an integer array
*/
public int[] intersection(int[] nums1, int[] nums2) { //HashSet方法,time:O(n)
Set<Integer> set=new HashSet<>();
Set<Integer> intersect=new HashSet<>();
for(int i=0;i<nums1.length;i++){
if(!set.contains(nums1[i])){
set.add(nums1[i]);
}
}
for(int i=0;i<nums2.length;i++){
if(set.contains(nums2[i])){
intersect.add(nums2[i]);
}
}
int[] result=new int[intersect.size()];
int i=0;
for(Integer num:intersect){
result[i++]=num;
}
return result;
}
}
public class Solution {
/**
* @param nums1 an integer array
* @param nums2 an integer array
* @return an integer array
*/
public int[] intersection(int[] nums1, int[] nums2) { //Sort arrays方法,time:O(nlogn)
Arrays.sort(nums1); //先sort
Arrays.sort(nums2);
Set<Integer> set=new HashSet<>();
int i=0,j=0;
while(i<nums1.length && j<nums2.length){
if(nums1[i]<nums2[j]){ //哪个小哪个向前走一步
i++;
}else if(nums[i]>nums2[j]){
j++;
}else{ //两个相等的时候就加入到set,并且两个同时向前走一步
set.add(nums1[i]);
i++;
j++;
}
}
int[] result=new int[set.size()];
int index=0;
for(Integer num:set){
result[index++]=num;
}
return result;
}
}
public class Solution {
/**
* @param nums1 an integer array
* @param nums2 an integer array
* @return an integer array
*/
public int[] intersection(int[] nums1, int[] nums2) { //binarySearch方法,time:O(nlogn)
if (nums1 == null || nums2 == null) {
return null;
}
Set<Integer> set = new HashSet<>();
Arrays.sort(nums1);
for (int i = 0; i < nums2.length; i++) {
if (binarySearch(nums1, nums2[i])) {
set.add(nums2[i]);
}
}
int[] result = new int[set.size()];
int index = 0;
for (Integer num : set) {
result[index++] = num;
}
return result;
}
private boolean binarySearch(int[] nums,int target){
if(nums==null || nums.length==0){
return false;
}
int start=0, end=nums.length-1;
while (start + 1 < end) {
int mid=(end-start)/2+start;
if(nums[mid]==target) {
return true;
}
if(nums[mid]<target) {
start = mid;
}else {
end = mid;
}
}
if(nums[start]==target) {
return true;
}
if(nums[end]==target) {
return true;
}
return false;
}
}
548.Intersection of Two ArraysII : 点击打开链接
public class Solution {
/**
* @param nums1 an integer array
* @param nums2 an integer array
* @return an integer array
*/
public int[] intersection(int[] nums1, int[] nums2) { //输出所有的重复元素
if(nums1==null || nums2==null){
return null;
}
Arrays.sort(nums1);
Arrays.sort(nums2);
List<Integer> temp=new ArrayList<>(); //换成一个list乘装暂时的重复元素,再向数组里倒
int i=0,j=0;
while(i<nums1.length && j<nums2.length){
if(nums1[i]<nums2[j]){
i++;
}else if(nums1[i]>nums2[j]){
j++;
}else{
temp.add(nums1[i]);
i++;
j++;
}
}
int[] result=new int[list.size()];
int index=0;
for(Integer num:list){
result[index++]=num;
}
return result;
}
}
65.Median of Two Sorted Arrays:点击打开链接
1. 如果数组A和B的总长度length是奇数,中位数就是第length / 2 + 1小的数,
如果length是偶数,中位数就是第length / 2小的数和length / 2 + 1小的数的平均数。
2. 要在两个排序的数组A和B(记成新数组)中找第k小的数,
我们希望用O(1)的时间把问题分解成:在数组A和数组B中分别找第k / 2小的数。
3. 我们比较数组A中第k / 2小的数和数组B中第k / 2小的数:
如果A[k / 2 - 1] < B[k / 2 - 1],说明在新数组中第k小的数不可能是A[k/2 - 1]以及这个数之前的数字,
那么我们可以把这k / 2个数字从A数组中踢掉,并在B数组和 过数的A数组里 分别找第k / 2小的数。
同理,如果B[k / 2 - 1] < A[k / 2 - 1],我们可以把k / 2个数字从B数组中踢掉,并在A数组和踢过数的B数组里分别找第k / 2小的数。
class Solution {
/**
* @param A: An integer array.
* @param B: An integer array.
* @return: a double whose format is *.5 or *.0
*/
public double findMedianSortedArrays(int[] A, int[] B) {
int length=A.length+B.length;
if(length%2==0){
return (findKth(A,0,B,0,length/2)+findKth(A,0,B,0,length/2+1))/2.0;
}
return findKth(A,0,B,0,length/2+1);
}
private int findKth(int[] A,int startA,int[] B,int startB,int k){
if(startA>=A.length){ //如果A变成null,就成了B数组单独找Kth
return B[startB+k-1];
}
if(startB>=B.length){ //如果B变成null,就成了A数组单独找Kth
return A[startA+k-1];
}
if(k==1){ //如果找第一大的数,就是A,B数组中的第一个小值
return Math.min(A[startA],B[startB]);
}
int valueA=startA+k/2-1<A.length?A[startA+k/2-1]:Integer.MAX_VALUE; //哪个数组不够了,就用无穷大后面补全
int valueB=startB+k/2-1<B.length?B[startB+k/2-1]:Integer.MAX_VALUE;
if(valueA<valueB){
return findKth(A,startA+k/2,B,startB,k-k/2);
}
return findKth(A,startA,B,startB+k/2,k-k/2);
}
}
41. Mixmam Subarray:点击打开链接
PrefixSum[i]=nums[0]+nums[1]+...+nums[i-1],PrefixSum[0]=0;
例如:int [ ] num={1,2,3,4,-5}
PrefixSum[0]=0,
PrefixSum[1]=nums[0]=1;
PrefixSum[2]=nums[0]+nums[1]=1+2=3;
PrefixSum[3]=nums[0]+nums[1]+nums[2]=1+2+3=6;
PrefixSum[4]=nums[0]+nums[1]+nums[2]+nums[3]=1+2+3+4=10;
PrefixSum[5]=nums[0]+nums[1]+nums[2]+nums[3]+nums[4]=1+2+3+4+(-5)=5;
public class Solution {
/**
* @param nums: A list of integers
* @return: A integer indicate the sum of max subarray
*/
public int maxSubArray(int[] nums) {
if(nums==null || nums.length==0){
return 0;
}
int sum=0;
int maxVal=Integer.MIN_VALUE;
int minSum=0;
for(int i=0;i<nums.length;i++){
sum+=nums[i];
maxVal=Math.max(maxVal,sum-minSum); //每次拿到一个当前最大值,都要比较(当前最大值)与(当前sum-当前最小和)的小大
minSum=Math.min(minSum,sum); //如果当前sum-当前最小和,自然得到就是当前最大值
}
return maxVal;
}
}
42. Maximum SubArray II: 点击打开链接
public class Solution {
/**
* @param nums: A list of integers
* @return: An integer denotes the sum of max two non-overlapping subarrays
*/
public int maxTwoSubArrays(ArrayList<Integer> nums) {
int maxVal=Integer.MIN_VALUE;
int minSum=0;
int sum=0;
int[] left=new int[nums.size()];
for(int i=0;i<nums.size();i++){ //左边开始相加,left[i]表示到i当前的最大值
sum+=nums.get(i);
maxVal=Math.max(maxVal,sum-minSum);
minSum=Math.min(sum,minSum);
left[i]=maxVal;
}
maxVal=Integer.MIN_VALUE;
minSum=0;
sum=0;
int[] right=new int[nums.size()];
for(int i=nums.size()-1;i>=0;i--){ //右边开始相加,right[i]表示到i当前的最大值
sum+=nums.get(i);
maxVal=Math.max(maxVal,sum-minSum);
minSum=Math.min(sum,minSum);
right[i]=maxVal;
}
maxVal=Integer.MIN_VALUE;
for(int i=0;i<nums.size()-1;i++){
maxVal=Math.max(maxVal,left[i]+right[i+1]); //最后对每一个左边最大,与比它向后一个位置的右边最大的和取最大
}
return maxVal;
}
}
138.Subarray Sum:点击打开链接
思路:子数组和为一个数,无非就是两种情况,从头开始的subarray,和从中间某一个位置开始的subarray
对于从中间某一位置i开始的subarray,例如前i位置之和为3,而从i+1 ~ j这一段加起来还是3,说明i+1 ~ j这段和为0
注意:如果需要计算子数组从下标i到下标j之间的所有数之和,则有:Sum(i~j)=PrefixSum[j+1]-PrefixSum[i]
public class Solution {
/**
* @param nums: A list of integers
* @return: A list of integers includes the index of the first number
* and the index of the last number
*/
public ArrayList<Integer> subarraySum(int[] nums) { //方法一
ArrayList<Integer> result=new ArrayList<>();
if(nums==null || nums.length==0){
return result;
}
Map<Integer,Integer> map=new HashMap<>();
int sum=0;
for(int i=0;i<nums.length;i++){
sum+=nums[i];
if(!map.containsKey(sum)){ //从头开始的每一个preSum
map.put(sum,i);
if(sum==0){
result.add(0);
result.add(i);
break;
}
}else{ //非从头开始(中间段)的每一个preSum
result.add(map.get(sum)+1);
result.add(i);
break;
}
}
return result;
}
}
public class Solution {
/**
* @param nums: A list of integers
* @return: A list of integers includes the index of the first number
* and the index of the last number
*/
public ArrayList<Integer> subarraySum(int[] nums) { //方法二:同样思路
ArrayList<Integer> ans = new ArrayList<Integer>();
HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
map.put(0, -1); //先放入sum为0,位置为-1
int sum = 0;
for (int i = 0; i <nums.length; i++) {
sum += nums[i];
if (map.containsKey(sum)) { //有同样的sum出现,就取之前出现sum的前一个位置和当前sum位置
ans.add(map.get(sum) + 1);
ans.add(i);
return ans;
}
map.put(sum, i); //只要有新的sum就放入到sum和位置i,表示从0开始到i的这段sum
}
return ans;
}
}
560. Subarray Sum Equals K:点击打开链接
public class Solution {
public int subarraySum(int[] nums, int k) {
if(nums==null || nums.length==0){
return 0;
}
Map<Integer,Integer> map=new HashMap<>();
int result=0;
int sum=0;
map.put(0,1); //考虑到从头开始的情况,要先放入sum为0,次数为1,不然会空指针异常
for(int i=0;i<nums.length;i++){
sum+=nums[i];
if(map.containsKey(sum-k)){ //每到一个数
result+=map.get(sum-k);
}
map.put(sum,map.getOrDefault(sum,0)+1); //用map来保存当前数组从头开始的前i项和的次数
}
return result;
}
}
public class Solution {
public int subarraySum(int[] nums, int k) { //brute force方法
if(nums==null || nums.length==0){
return 0;
}
int count=0;
for(int i=0;i<nums.length;i++){
int sum=0;
sum+=nums[i];
if(sum==k){
count++;
}
for(int j=i+1;j<nums.length;j++){
sum+=nums[j];
if(sum==k){
count++;
}
}
}
return count;
}
}
139.Subarray Sum Closet: 点击打开链接
class Pair {
int sum;
int index;
public Pair(int sum, int index) {
this.sum = sum;
this.index = index;
}
}
public class Solution {
/**
* @param nums: A list of integers
* @return: A list of integers includes the index of the first number
* and the index of the last number
*/
public int[] subarraySumClosest(int[] nums) {
int[] result=new int[2];
if(nums==null || nums.length==0){
return result;
}
int len=nums.length;
if(len==1){
result[0]=result[1]=0;
}
Pair[] preSum=new Pair[len+1]; //preSum表示的是前i个元素和,和对应的索引i-1
int pre=0; //也就是preSum[3],前3个元素和,是0,1,2,因此索引是2
preSum[0]=new Pair(0,0);
for(int i=1;i<=len;i++){ //for循环拿到前i个元素和
preSum[i]=new Pair(pre+nums[i-1],i);
pre=preSum[i].sum;
}
Arrays.sort(preSum,new Comparator<Pair>(){ //然后重新排序preSum,按照和的大小
public int compare(Pair p1,Pair p2){ //因此重新排序后preSum表示的在数组preSum中第几大
return p1.sum-p2.sum;
}
});
int closet=Integer.MAX_VALUE;
for(int i=1;i<=len;i++){
if(preSum[i].sum-preSum[i-1].sum<closet){ //两两一次遍历记录当前最小的差,也就是对应的索引差最接近0
closet=preSum[i].sum-preSum[i-1].sum;
int[] temp=new int[]{preSum[i-1].index-1,preSum[i].index-1};
Arrays.sort(temp);
result[0]=temp[0]+1;
result[1]=temp[1];
}
}
return result;
}
}