15,3sum
Given an array nums
of n integers, are there elements a, b, c 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 a, b, c, 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;
}