leetcode_ array

Copyright: https://blog.csdn.net/qq_40722284/article/details/89085740

15,3sum

Given an array nums of n integers, are there elements abc in nums such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.

Note:

The solution set must not contain duplicate triplets.

Example:

Given array nums = [-1, 0, 1, 2, -1, -4],

A solution set is:
[
  [-1, 0, 1],
  [-1, -1, 2]
]

Ideas:
1. first sorting array;
2, in the case of a known value, and find the other two values;
3, find the other two bidirectional pointers and values;

public List<List<Integer>> threeSum(int[] nums) {
        Arrays.sort(nums);
        List<List<Integer>> alist = new ArrayList<List<Integer>>();
        for(int i = 0; i < nums.length - 2; i++){
            if(i == 0 || (i > 0 && nums[i] != nums[i - 1])){ //避免了第一个值重复
                int lo = i + 1; 
                int hi = nums.length - 1;
                int sum = 0 - nums[i];
                while(lo < hi){
                    if(nums[lo] + nums[hi] == sum){
                        alist.add(Arrays.asList(nums[i], nums[lo], nums[hi]));
                        while(lo < hi && nums[lo] == nums[lo + 1]) lo++;
                        while(lo < hi && nums[hi] == nums[hi - 1]) hi--;
                        lo++;
                        hi--;
                    }else if(nums[lo] + nums[hi] < sum) lo++;
                    else hi--;
                }
            }
        }
        return alist;
    }

Arrays.asList

 * 本类演示了Arrays类中的asList方法 
 * 通过四个段落来演示,体现出了该方法的相关特性. 
 *  
 * (1) 该方法对于基本数据类型的数组支持并不好,当数组是基本数据类型时不建议使用 
 * (2) 当使用asList()方法时,数组就和列表链接在一起了. 
 *     当更新其中之一时,另一个将自动获得更新。 
 *     注意:仅仅针对对象数组类型,基本数据类型数组不具备该特性 
 * (3) asList得到的数组是的没有add和remove方法的 
 *  
 * 阅读相关:通过查看Arrays类的源码可以知道,asList返回的List是Array中的实现的 
 * 内部类,而该类并没有定义add和remove方法.另外,为什么修改其中一个,另一个也自动 
 * 获得更新了,因为asList获得List实际引用的就是数组 

16. 3Sum Closest

Given an array nums of n integers and an integer target, find three integers in nums such that the sum is closest to target. Return the sum of the three integers. You may assume that each input would have exactly one solution.

Example:

Given array nums = [-1, 2, 1, -4], and target = 1.
The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).

Ideas:
1, three comparison target number and the size of the
two, left and right pointers updated constantly closer to the target (sum> target reduced hi, increase or LO)

public int threeSumClosest(int[] nums, int target) {
        Arrays.sort(nums);
        int res = Integer.MAX_VALUE;
        int index = 0;
        for(int i = 0; i < nums.length - 2; i++){
                int lo = i + 1; 
                int hi = nums.length - 1;
                while(lo < hi){
                    int sum = nums[i] + nums[lo] + nums[hi];
                    if(res > Math.abs(sum - target)){
                        res = Math.abs(sum - target);
                        index = sum;  
                        if(res == 0) return target;                
                    }
                    if(target < sum) hi--;
                    else lo++;
                }
            
        }
        return index;
    }

18. 4Sum

Given an array nums of n integers and an integer target, are there elements abc, and d in nums such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.

Note:

The solution set must not contain duplicate quadruplets.

Example:

Given array nums = [1, 0, -1, 0, -2, 2], and target = 0.

A solution set is:
[
  [-1,  0, 0, 1],
  [-2, -1, 1, 2],
  [-2,  0, 0, 2]
]

Ideas:
four and number of problem into three and the number of questions, one more cycle

public List<List<Integer>> fourSum(int[] nums, int target) {
          Arrays.sort(nums);
		 List<List<Integer>> aList = new ArrayList<List<Integer>>();
		 for (int i = 0; i < nums.length - 3; i++) {
			 if(i == 0 ||  (i > 0 && nums[i] != nums[i - 1])) {
				 int curtarget = target - nums[i];
				 //求三数和的问题
				 for(int start = i + 1; start < nums.length - 2; start++) {
					 if(start == i + 1 || (start > i + 1 && 
                                           nums[start] != nums[start - 1])) {
						 int lo = start + 1;
						 int hi = nums.length - 1;
						 while(lo < hi) {
							 int sum = nums[start] + nums[lo] + nums[hi];
							 if(sum == curtarget) {
								 aList.add(Arrays.asList(nums[i], nums[start],
                                                         nums[lo],nums[hi]));
								 while(lo < hi && nums[lo] == nums[lo + 1]) lo++;
								 while(lo < hi && nums[hi] == nums[hi - 1]) hi--;
								 lo++;
								 hi--;
							 }else if(sum > curtarget) {
								 hi--;
							 }else {
								 lo++;
							 }
						 }
					 }
				 }
			 }
					
		}
		 return aList;
    }

K and seeking common way several issues

问题分析如下
1、2sum Problem
2、Reduce K sum problem to K – 1 sum Problem(使用递归)
Time complexity is O(N^(K-1)).
=====================================================================================

    public class Solution {
        int len = 0;
        public List<List<Integer>> fourSum(int[] nums, int target) {
            len = nums.length;
            Arrays.sort(nums);
            return kSum(nums, target, 4, 0);
        }
       private ArrayList<List<Integer>> kSum(int[] nums, int target, int k, int index) {
            ArrayList<List<Integer>> res = new ArrayList<List<Integer>>();
            if(index >= len) {
                return res;
            }
            if(k == 2) {
            	int i = index, j = len - 1;
            	while(i < j) {
                    //find a pair
            	    if(target - nums[i] == nums[j]) {
            	    	List<Integer> temp = new ArrayList<>();
                    	temp.add(nums[i]);
                    	temp.add(target-nums[i]);
                        res.add(temp);
                        //skip duplication
                        while(i<j && nums[i]==nums[i+1]) i++;
                        while(i<j && nums[j-1]==nums[j]) j--;
                        i++;
                        j--;
                    //move left bound
            	    } else if (target - nums[i] > nums[j]) {
            	        i++;
                    //move right bound
            	    } else {
            	        j--;
            	    }
            	}
            } else{
                for (int i = index; i < len - k + 1; i++) {
                    //use current number to reduce ksum into k-1sum
                    ArrayList<List<Integer>> temp = kSum(nums, target - nums[i], k-1, i+1);
                    if(temp != null){
                        //add previous results
                        for (List<Integer> t : temp) {
                            t.add(0, nums[i]);
                        }
                        res.addAll(temp);
                    }
                    while (i < len-1 && nums[i] == nums[i+1]) {
                        //skip duplicated numbers
                        i++;
                    }
                }
            }
            return res;
        }
    }

31. Next Permutation

Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers.

If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending order).

The replacement must be in-place and use only constant extra memory.

Here are some examples. Inputs are in the left-hand column and its corresponding outputs are in the right-hand column.

1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1

题意理解:
数组从后往前看找到第一个下降的数,
然后在从后往前找到第一个比刚找的数大的数,
两者交换,
再将第一个位置之后的数据转置一下。

public void nextPermutation(int[] nums) {
       int pivot = nums.length - 1;
        while (pivot > 0 && nums[pivot] <= nums[pivot-1]) {
            pivot--;
        }
        if (pivot != 0) {
            int nextPivot = nums.length - 1;
            while (pivot - 1 < nextPivot && nums[pivot-1] >= nums[nextPivot]) {
                nextPivot--;
            }
            swap(nums, pivot-1, nextPivot);
        }
        reverseArray(nums, pivot, nums.length - 1);
    } 
    private void reverseArray(int[] nums, int start, int end) {
        while (start < end) {
            swap(nums, start++, end--);
        }
    }
	public void swap(int[] arr, int i, int j) {
		int tmp = arr[i];
		arr[i] = arr[j];
		arr[j] = tmp;
	}

33. Search in Rotated Sorted Array

Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.

(i.e., [0,1,2,4,5,6,7] might become [4,5,6,7,0,1,2]).

You are given a target value to search. If found in the array return its index, otherwise return -1.

You may assume no duplicate exists in the array.

Your algorithm's runtime complexity must be in the order of O(log n).

Example 1:

Input: nums = [4,5,6,7,0,1,2], target = 0
Output: 4

Example 2:

Input: nums = [4,5,6,7,0,1,2], target = 3
Output: -1

Ideas:
a direct comparison of the middle position
and the first element in an intermediate position in comparison to see which half-area
update about the nodes in the corresponding half-area, do binary search

 public int search(int[] nums, int target) {
        
        if(nums.length < 1 || nums == null)
            return -1;
        int lo = 0;
        int hi = nums.length - 1;
        while(lo < hi){
            int mid = lo + ((hi - lo) >> 1);
            if(nums[mid] >= nums[lo]){  //确定中间值落在哪个区域,这里是落在大半区
                if(target <= nums[mid] && target >= nums[lo]) hi = mid;
                else lo = mid + 1;
            }else{          //落在小半区
                if(target > nums[mid] && target <= nums[hi]) lo = mid + 1;
                else hi = mid;
            }
        }
        return nums[lo] == target ? lo : -1;
    }

81. Search in Rotated Sorted Array II

Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.

(i.e., [0,0,1,2,2,5,6] might become [2,5,6,0,0,1,2]).

You are given a target value to search. If found in the array return true, otherwise return false.

Example 1:

Input: nums = [2,5,6,0,0,1,2], target = 0
Output: true

Example 2:

Input: nums = [2,5,6,0,0,1,2], target = 3
Output: false

Thinking:
binary search
because there will be a first value and a value equal to the last case, it should be relatively midpoint and end value (Hi)
MID is greater than hi, the first half region;
MID less than hi, in the latter half region;
equal , whether before or after the time, the mobile lo, hi come ranging region;

public boolean search(int[] nums, int target) {
        if(nums == null || nums.length < 1) 
            return false;
        int lo = 0;
        int hi = nums.length - 1;
        while(lo <= hi){
            int mid = lo + ((hi - lo) >> 1);
            if(nums[mid] == target) 
                return true;
            if(nums[mid] < nums[hi]){  
                if(nums[hi] < target || target < nums[mid]){  
                    hi = mid - 1;
                }else{
                    lo = mid + 1;
                }
            }else if(nums[mid] > nums[hi]){
                if(nums[mid] < target || target < nums[lo]){ 
                   lo = mid + 1;
                }else{
                    hi = mid - 1;
                }
            }else{
                 while(lo <= hi && nums[lo] == nums[mid]) lo++;
                 while(lo <= hi && nums[hi] == nums[mid]) hi--;
            }
                
        }
        
        return false; 
    }

34. Find First and Last Position of Element in Sorted Array

Given an array of integers nums sorted in ascending order, find the starting and ending position of a given target value.

Your algorithm's runtime complexity must be in the order of O(log n).

If the target is not found in the array, return [-1, -1].

Example 1:

Input: nums = [5,7,7,8,8,10], target = 8
Output: [3,4]

Example 2:

Input: nums = [5,7,7,8,8,10], target = 6
Output: [-1,-1]

Ideas:
first determine two endpoints
using binary searching in an intermediate position, and then by comparing the region at which half
around the subject as the mobile element if the element at different
note, (8,8,10,10) appears adjacent target positions = 0900 needs a break condition

 public int[] searchRange(int[] nums, int target) {
         if(nums == null || nums.length < 1)
	        	return new int[]{-1, -1};
	        int lo = 0;
	        int hi = nums.length - 1;
	        int[] res = new int[2];
	        if(target == nums[lo]){
	        	res[0] = 0;
	        	int i = 0;
	        	while(i <= hi){
	        		if(nums[i] == nums[0]){
	        			i++;
	        		}else {
						break;
					}
	        	}
	        	res[1] = i - 1;
	        	return res;
	        }
	        if(target == nums[hi]){
	        	res[1] = hi;
	        	int i = hi;
	        	while(i >= 0){
	        		if(nums[i] == nums[hi]){
	        			i--;
	        		}else {
						break;
					}
	        	}
	        	res[0] = i + 1;
	        	return res;
	        }	
	        while(lo <= hi){
	        	int mid = lo + ((hi - lo) >> 1);
	        	if(nums[mid] < target && target < nums[hi] ){
	        		while(mid + 1 <= hi && nums[mid] == nums[mid + 1]) mid++;
	        		while(hi - 1 >= mid && nums[hi] == nums[hi - 1]) hi--;
	        		lo = mid;
	        		if(mid + 1 == hi){
	        			res[0] = -1;
						res[1] = -1;
						break;
	        		}	
	        	}else if(nums[mid] > target && target > nums[lo]){
	        		while(mid - 1 >= lo && nums[mid] == nums[mid - 1]) mid--;
	        		while(lo + 1 <= mid && nums[lo] == nums[lo + 1]) lo++;
	        		hi = mid;
	        		if(mid - 1 == lo){
	        			res[0] = -1;
						res[1] = -1;
						break;
	        		}
				}else if(target == nums[mid]){
					while(nums[mid] == nums[mid + 1] && mid < hi) mid++;
					res[1] = mid;
					while(nums[mid] == nums[mid - 1] && mid > lo ) mid--;
					res[0] = mid;
					break;
				}else {
					res[0] = -1;
					res[1] = -1;
					break;
				}
	        }
	        return res;
    }

General structure

Subsets : https://leetcode.com/problems/subsets/

public List<List<Integer>> subsets(int[] nums) {
    List<List<Integer>> list = new ArrayList<>();
    Arrays.sort(nums);
    backtrack(list, new ArrayList<>(), nums, 0);
    return list;
}

private void backtrack(List<List<Integer>> list , List<Integer> tempList, int [] nums, int start){
    list.add(new ArrayList<>(tempList));
    for(int i = start; i < nums.length; i++){
        tempList.add(nums[i]);
        backtrack(list, tempList, nums, i + 1);
        tempList.remove(tempList.size() - 1);
    }
}
Subsets II (contains duplicates) : https://leetcode.com/problems/subsets-ii/

public List<List<Integer>> subsetsWithDup(int[] nums) {
    List<List<Integer>> list = new ArrayList<>();
    Arrays.sort(nums);
    backtrack(list, new ArrayList<>(), nums, 0);
    return list;
}

private void backtrack(List<List<Integer>> list, List<Integer> tempList, int [] nums, int start){
    list.add(new ArrayList<>(tempList));
    for(int i = start; i < nums.length; i++){
        if(i > start && nums[i] == nums[i-1]) continue; // skip duplicates
        tempList.add(nums[i]);
        backtrack(list, tempList, nums, i + 1);
        tempList.remove(tempList.size() - 1);
    }
} 
Permutations : https://leetcode.com/problems/permutations/

public List<List<Integer>> permute(int[] nums) {
   List<List<Integer>> list = new ArrayList<>();
   // Arrays.sort(nums); // not necessary
   backtrack(list, new ArrayList<>(), nums);
   return list;
}

private void backtrack(List<List<Integer>> list, List<Integer> tempList, int [] nums){
   if(tempList.size() == nums.length){
      list.add(new ArrayList<>(tempList));
   } else{
      for(int i = 0; i < nums.length; i++){ 
         if(tempList.contains(nums[i])) continue; // element already exists, skip
         tempList.add(nums[i]);
         backtrack(list, tempList, nums);
         tempList.remove(tempList.size() - 1);
      }
   }
} 
Permutations II (contains duplicates) : https://leetcode.com/problems/permutations-ii/

public List<List<Integer>> permuteUnique(int[] nums) {
    List<List<Integer>> list = new ArrayList<>();
    Arrays.sort(nums);
    backtrack(list, new ArrayList<>(), nums, new boolean[nums.length]);
    return list;
}

private void backtrack(List<List<Integer>> list, List<Integer> tempList, int [] nums, boolean [] used){
    if(tempList.size() == nums.length){
        list.add(new ArrayList<>(tempList));
    } else{
        for(int i = 0; i < nums.length; i++){
            if(used[i] || i > 0 && nums[i] == nums[i-1] && !used[i - 1]) continue;
            used[i] = true; 
            tempList.add(nums[i]);
            backtrack(list, tempList, nums, used);
            used[i] = false; 
            tempList.remove(tempList.size() - 1);
        }
    }
}
Combination Sum : https://leetcode.com/problems/combination-sum/

public List<List<Integer>> combinationSum(int[] nums, int target) {
    List<List<Integer>> list = new ArrayList<>();
    Arrays.sort(nums);
    backtrack(list, new ArrayList<>(), nums, target, 0);
    return list;
}

private void backtrack(List<List<Integer>> list, List<Integer> tempList, int [] nums, int remain, int start){
    if(remain < 0) return;
    else if(remain == 0) list.add(new ArrayList<>(tempList));
    else{ 
        for(int i = start; i < nums.length; i++){
            tempList.add(nums[i]);
            backtrack(list, tempList, nums, remain - nums[i], i); // not i + 1 because we can reuse same elements
            tempList.remove(tempList.size() - 1);
        }
    }
}
Combination Sum II (can't reuse same element) : https://leetcode.com/problems/combination-sum-ii/

public List<List<Integer>> combinationSum2(int[] nums, int target) {
    List<List<Integer>> list = new ArrayList<>();
    Arrays.sort(nums);
    backtrack(list, new ArrayList<>(), nums, target, 0);
    return list;
    
}

private void backtrack(List<List<Integer>> list, List<Integer> tempList, int [] nums, int remain, int start){
    if(remain < 0) return;
    else if(remain == 0) list.add(new ArrayList<>(tempList));
    else{
        for(int i = start; i < nums.length; i++){
            if(i > start && nums[i] == nums[i-1]) continue; // skip duplicates
            tempList.add(nums[i]);
            backtrack(list, tempList, nums, remain - nums[i], i + 1);
            tempList.remove(tempList.size() - 1); 
        }
    }
} 
Palindrome Partitioning : https://leetcode.com/problems/palindrome-partitioning/

public List<List<String>> partition(String s) {
   List<List<String>> list = new ArrayList<>();
   backtrack(list, new ArrayList<>(), s, 0);
   return list;
}

public void backtrack(List<List<String>> list, List<String> tempList, String s, int start){
   if(start == s.length())
      list.add(new ArrayList<>(tempList));
   else{
      for(int i = start; i < s.length(); i++){
         if(isPalindrome(s, start, i)){
            tempList.add(s.substring(start, i + 1));
            backtrack(list, tempList, s, i + 1);
            tempList.remove(tempList.size() - 1);
         }
      }
   }
}

public boolean isPalindrome(String s, int low, int high){
   while(low < high)
      if(s.charAt(low++) != s.charAt(high--)) return false;
   return true;
} 

 

 

 

 

 

 

 

 

 

 

 

 

 

Guess you like

Origin blog.csdn.net/qq_40722284/article/details/89085740