#include <iostream>
#include <unordered_map>
#include <vector>
#include <algorithm>
using namespace std;
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode() : val(0), left(nullptr), right(nullptr) {}
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};
void print(const vector<int>& nums)
{
for (int num : nums)
{
cout << num << " ";
}
cout << endl;
}
void print(const vector<vector<int>>& nums)
{
for (auto num : nums)
{
for (auto num_ : num)
{
cout << num_ << " ";
}
cout << endl;
}
cout << endl;
}
vector<int>twoSum(const vector<int>& nums, int target)
{
unordered_map<int, int>map;
for (int i = 0; i < nums.size(); ++i)
{
int diff = target - nums[i];
if (map.find(diff) != map.end())
{
return { map.at(diff),i };
}
map[nums[i]] = i;
}
return { -1,-1 };
}
vector<int>twoSum0(const vector<int>& nums, int target)
{
int left = 0, right = nums.size() - 1;
while (left < right)
{
int tmp = nums[left] + nums[right];
if (tmp == target)return { left + 1,right + 1 };
else if (tmp > target)--right;
else ++left;
}
return {};
}
void inorder(TreeNode* root, vector<int>& nums)
{
if (nullptr == root)return;
inorder(root->left, nums);
nums.emplace_back(root->val);
inorder(root->right, nums);
}
bool findTarget(TreeNode* root, int k) {
vector<int>nums;
inorder(root, nums);
int left = 0, right = nums.size() - 1;
while (left < right)
{
int tmp = nums[left] + nums[right];
if (tmp == k)return true;
else if (tmp > k) --right;
else ++left;
}
return false;
}
void twoSum(vector<int>& nums, int left, int right, int target, vector<vector<int>>& res)
{
while (left < right)
{
int tmp = nums[left] + nums[right] + target;
if (0 == tmp)
{
res.push_back({ target,nums[left++],nums[right--] });
while (nums[left] == nums[left - 1] && left < right)++left;
while (nums[right] == nums[right + 1] && left < right)--right;
}
else if (tmp > 0)--right;
else ++left;
}
return;
}
vector<vector<int>>ThreeSum(vector<int>& nums)
{
sort(nums.begin(), nums.end());
vector<vector<int>>res;
for (int i = 0; i < nums.size() - 2; ++i)
{
if (i != 0 && nums[i] == nums[i - 1])continue;
int left = i + 1, right = nums.size() - 1;
twoSum(nums, left, right, nums[i], res);
}
return res;
}
int ThreeSumClosest(vector<int>&nums, int target)
{
int n = nums.size();
int res = nums[0] + nums[1] + nums[n - 1];
sort(nums.begin(), nums.end());
for (int i = 0; i < n - 2; ++i)
{
int left = i + 1, right = n - 1;
while (left < right)
{
int sum = nums[left] + nums[right] + nums[i];
if (abs(sum - target) < abs(res - target))
{
res = sum;
}
if (sum > target)--right;
else ++left;
}
}
return res;
}
int threeSumSmaller(vector<int>&nums, int target)
{
sort(nums.begin(), nums.end());
int cnt = 0;
for (int i = 0; i < nums.size() - 2; ++i)
{
int left = i + 1, right = nums.size() - 1;
while (left < right)
{
if (nums[left] + nums[right] + nums[i] >= target)--right;
else
{
cnt += right - left;
++left;
}
}
}
return cnt;
}
vector<vector<int>>fourSum(vector<int>& nums, int target)
{
sort(nums.begin(), nums.end());
vector<vector<int>>res;
int n = nums.size(), left, right, sum;
for (int i = 0; i < n - 3; ++i)
{
if (i != 0 && nums[i] == nums[i - 1])continue;
for (int j = i + 1; j < n - 2; ++j)
{
if (j != i + 1 && nums[j] == nums[j - 1])continue;
left = j + 1, right = n - 1;
while (left < right)
{
sum = nums[i] + nums[j] + nums[left] + nums[right];
if (target == sum)
{
res.push_back({ nums[i],nums[j],nums[left++],nums[right--] });
while (left < right && nums[left] == nums[left - 1]) ++left;
while (left < right && nums[right] == nums[right + 1])--right;
}
else if (sum > target)--right;
else ++left;
}
}
}
return res;
}
int fourSumCnt(const vector<int>&a, const vector<int>&b, const vector<int>&c, const vector<int>&d)
{
unordered_map<int, int>map;
for (int i = 0; i < c.size(); ++i)
{
for (int j = 0; j < d.size(); ++j)
{
int sum = c[i] + d[j];
++map[sum];
}
}
int res = 0;
for (int i = 0; i < a.size(); ++i)
{
for (int j = 0; j < b.size(); ++j)
{
int tmp = -(a[i] + b[j]);
if (map.find(tmp) != map.end())
res += map.at(tmp);
}
}
return res;
}
int kSum(const vector<int>& nums, int k, int target)
{
int n = nums.size();
vector<vector<vector<int>>>dp(n + 1, vector<vector<int>>(k + 1, vector<int>(target + 1)));
for (int i = 0; i <= n; ++i)dp[i][0][0] = 1;
for (int i = 1; i <= n; ++i)
{
for (int j = 1; j <= k && j <= i; ++j)
{
for (int t = 1; t <= target; ++t)
{
dp[i][j][t] = 0;
if (t >= nums[i - 1])
{
dp[i][j][t] = dp[i - 1][j - 1][t - nums[i - 1]];
}
dp[i][j][t] += dp[i - 1][j][t];
}
}
}
return dp[n][k][target];
}
void dfs(vector<int>& nums, int index, int remainCnt, int remainTarget, vector<int>&subset, vector<vector<int>>& res)
{
if (remainCnt == 0 && remainTarget == 0)
{
res.emplace_back(subset);
return;
}
if (remainCnt == 0)return;
for (int i = index; i < nums.size(); ++i)
{
if (nums[index] > remainTarget)break;
subset.emplace_back(nums[i]);
dfs(nums, index + 1, remainCnt - 1, remainTarget - nums[i], subset, res);
subset.pop_back();
}
}
vector<vector<int>>kSumII(vector<int>&nums, int k, int target)
{
vector<vector<int>>res;
vector<int>tmp;
sort(nums.begin(), nums.end());
dfs(nums, 0, k, target, tmp, res);
return res;
}
int main() {
//LeetCode1
vector<int>nums{ 2,7,11,5 };
int target = 9;
print(twoSum(nums, target));
//LeetCode167
vector<int>nums1{ 2,3,4 };
target = 6;
print(twoSum0(nums1, target));
////LeetCode653
//TreeNode a0(5);
//TreeNode a1(3);
//TreeNode a2(6);
//TreeNode a3(2);
//TreeNode a4(4);
//TreeNode a7(7);
//a0.left = &a1;
//a0.right = &a2;
//a1.left = &a3;
//a1.right = &a4;
//a2.right = &a7;
//int k = 28;
//cout << findTarget(&a0, k) << endl;
////LeetCode15
//vector<int>nums2{ -1,0,1,2,-1,-4 };
//print(ThreeSum(nums2));
////LeetCode16
//vector<int>nums3{ -1,2,1,-4 };
//int a = ThreeSumClosest(nums3, 1);
//cout << a << endl;
////LeetCode259
//vector<int>nums4{ -2,0,1,3 };
//target = 2;
//cout << threeSumSmaller(nums4, target) << endl;
////LeetCode18
//vector<int>nums5{ 2,2,2,2,2 };
//target = 8;
//auto res = fourSum(nums5, target);
//print(res);
////LeetCode454
//vector<int>nums_a = { 1,2 };
//vector<int>nums_b = { -2,-1 };
//vector<int>nums_c = { -1,2 };
//vector<int>nums_d = { 0,2 };
//int res0 = fourSumCnt(nums_a, nums_b, nums_c, nums_d);
//cout << res0 << endl;
////LeetCode89
//vector<int>nums6{ 1,3,4,6 };
//k = 3;
//target = 8;
//int t = kSum(nums6, k, target);
//cout << t << endl;
////LeetCode90
//print(kSumII(nums6, k, target));
return 0;
}