题1: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] ]
思路分析:
解法一:3sum+1的方法,在原有3sum基础上再加一层循环,去除重复的组合即可,时间复杂度O(n^3)。
(1)整个数组排序,遍历数组0~nums.size()-4,当前位置设为i,第一层循环 。
(2)遍历数组1~nums.size()-3,,当前位置设为j,第二层循环。
(3)在j~nums.size()-1之间,采用low=j+1,high=nums.size()-1,不断寻找目标值。
(4)通过(nums[low]+nums[high])与target-nums[i]-nums[j]的大小调整。前者大,high--;后者大low++
源码:
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
//解法2:时间复杂度O(n^3),两层遍历加一层
vector<vector<int>> res;
if(nums.size()<4) //去除不符合条件的数组
return res;
//排序
sort(nums.begin(),nums.end());
for(int i=0;i<nums.size()-3;i++)
{
for(int j=i+1;j<nums.size()-2;j++)
{
int sum = target - nums[i]-nums[j];
int low =j+1,high = nums.size()-1;
while(low<high)
{
if(sum > (nums[low]+nums[high]))
{
low++;
}
else if(sum < (nums[low]+nums[high]))
{
high--;
}
else
{
vector<int> quadruplet(4, 0);
quadruplet[0] = nums[i];
quadruplet[1] = nums[j];
quadruplet[2] = nums[low];
quadruplet[3] = nums[high];
res.push_back(quadruplet);
// Processing the duplicates of number 3
while (low < high && nums[low] == quadruplet[2]) ++low;
// Processing the duplicates of number 4
while (low < high && nums[high] == quadruplet[3]) --high;
}
}// Processing the duplicates of number 2
while(j + 1 < nums.size() && nums[j + 1] == nums[j]) ++j;
}
// Processing the duplicates of number 1
while (i + 1 < nums.size() && nums[i + 1] == nums[i]) ++i;
}
return res;
}
};
解法二:两次折半查找思想的循环,low1和high1、low2和high2(仅AC了60%),时间复杂度O(n^2)。
(1)整个数组排序,取两个指标low1=0和high1=nums.size()-1为外层循环的标记,第一层循环 。
(2)在low1~high1之间,设置low2 = low1+1,high2 = high1-1,作为内层循环的标记,第二层循环。
(3)两次循环的调整步骤相同,都是通过与target的比较来调整low1、low2、high1和high2。
问题:在外层循环的时候,不能将整个数组中的全部组合遍历完,所以出现问题。下面放出源码,待修改!
源码:
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
//解法1:时间复杂度 O(n^2),AC,60%,需要进一步修改
vector<vector<int>> res;
if(nums.size()<4)
return res;
sort(nums.begin(),nums.end());
int cnt=0;
int pos1 = 0,pos2 = nums.size()-1;
//内部元素为四个时,判断是够符合标准
if(pos2 - pos1 == 3 )
{
if((nums[0]+nums[1]+nums[2]+nums[3]) == target)
{
res.push_back(vector<int>{nums[0],nums[1],nums[2],nums[3]});
}
return res;
}
//内部元素大于四个,求组合
while(pos1 < pos2)
{
int low = pos1+1,high = pos2-1;
cnt=0;
int target2 = target - nums[pos1]-nums[pos2];
while(low<high)
{
int sum1 =nums[low] + nums[high];
if(target2 == sum1)
{
res.push_back(vector<int>{nums[pos1],nums[low],nums[high],nums[pos2]});
low++;high--;
}
else if(sum1>target2)
{
high--;
cnt++;
}
else if(sum1<target2)
{
low++;
cnt--;
}
}
if(cnt<0)pos1++;
else if(cnt>=0)pos2--;
}
return res;
}
};
题2:Merge k Sorted Lists
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
Example:
Input: [ 1->4->5, 1->3->4, 2->6 ] Output: 1->1->2->3->4->4->5->6
思路分析:
解法一:两组有序链表合并,递归此过程,直至链表数目为1。
(1)选择两组链表进行合并,可以按序合并比如1和2,1和3.....,直至1和n,也可1和n,2和n-1.....不断头尾合并(次数较少)。
(2)两组有序链表进行合并即可,详情见数据结构(严蔚敏版本)链表这一节。
源码:
class Solution {
public:
ListNode* mergeTwoLists(ListNode* list1,ListNode* list2)
{
if(list1 == NULL)return list2;
else if(list2 == NULL)return list1;
if(list1->val <= list2->val)
{
list1->next = mergeTwoLists(list1->next,list2);
return list1;
}
else
{
list2->next = mergeTwoLists(list1,list2->next);
return list2;
}
}
ListNode* mergeKLists(vector<ListNode*>& lists) {
if(lists.empty()) return NULL;
int len = lists.size();
while(len>1)
{
for(int i=0;i<len/2;++i)
{
lists[i] = mergeTwoLists(lists[i],lists[len-1-i]);
}
len = (len+1)/2;
}
return lists.front();
}
};
解法二:取所有链表的首个元素,共n个元素,组成一个堆,建立最小堆,输出根节点。
(1)初始化一个含有n个元素的容器,将每个链表的头节点放入,建立最小堆,输出根节点。
(2)将最小值对应的链表的值换成下一个节点的值,继续输入。