forked from keineahnung2345/leetcode-cpp-practices
-
Notifications
You must be signed in to change notification settings - Fork 0
/
1. Two Sum.cpp
165 lines (142 loc) · 4.56 KB
/
1. Two Sum.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
//sort + two pointer
//Runtime: 8 ms, faster than 99.93% of C++ online submissions for Two Sum.
//Memory Usage: 9.5 MB, less than 70.01% of C++ online submissions for Two Sum.
//time: O(NlogN), space: O(N)
class Solution {
public:
template <typename T>
vector<int> sort_indexes(const vector<T> &v) {
// initialize original index locations
vector<int> idx(v.size());
iota(idx.begin(), idx.end(), 0);
// sort indexes based on comparing values in v
sort(idx.begin(), idx.end(),
[&v](int i1, int i2) {return v[i1] < v[i2];});
return idx;
}
vector<int> twoSum(vector<int>& nums, int target) {
vector<int> ixs = sort_indexes(nums);
int i = 0, j = nums.size()-1;
while(i < j){
int ix1 = ixs[i], ix2 = ixs[j];
if(nums[ix1] + nums[ix2] == target){
return vector<int> {ix1, ix2};
}else if(nums[ix1] + nums[ix2] < target){
i++;
}else{
j--;
}
}
return vector<int>();
}
};
//sort + two pointer, easier to understand
//https://leetcode.com/problems/two-sum/discuss/7/Java-O(nlogn)-beats-98.85
//Runtime: 340 ms, faster than 86.87% of C++ online submissions for Number of Subsequences That Satisfy the Given Sum Condition.
//Memory Usage: 50.1 MB, less than 100.00% of C++ online submissions for Number of Subsequences That Satisfy the Given Sum Condition.
//time: O(NlogN), space: O(N)
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
/*
we still need nums to get the numbers' indices,
so here we make a copy
*/
int n = nums.size();
vector<int> nums2 = nums;
sort(nums2.begin(), nums2.end());
//find the two elements whose sum is target is the sorted array
int a, b;
for(int l = 0, r = n-1; l <= r; ){
if(nums2[l] + nums2[r] < target){
++l;
}else if(nums2[l] + nums2[r] > target){
--r;
}else{
a = nums2[l];
b = nums2[r];
break;
}
}
//find a and b's indices in original array
vector<int> ans(2);
for(int i = 0; i < n; ++i){
if(nums[i] == a){
ans[0] = i;
break;
}
}
for(int i = n-1; i >= 0; --i){
if(nums[i] == b){
ans[1] = i;
break;
}
}
return ans;
}
};
/**
Approach 1: Brute Force
**/
/**
Complexity Analysis
Time complexity : O(n^2).
For each element,
we try to find its complement by looping through the rest of array which takes O(n) time.
Therefore, the time complexity is O(n^2).
Space complexity : O(1).
**/
/**
Approach 2: Two-pass Hash Table
build map and then check for each key whether its complement exists
**/
/**
Complexity Analysis:
Time complexity : O(n).
We traverse the list containing nn elements exactly twice.
Since the hash table reduces the look up time to O(1), the time complexity is O(n).
Space complexity : O(n).
The extra space required depends on the number of items stored in the hash table, which stores exactly nn elements.
**/
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
map<int, int> ixs;
for(int i = 0; i < nums.size(); i++){
ixs[nums[i]] = i;
}
for(int i = 0; i < nums.size(); i++){
int complement = target - nums[i];
if(ixs.find(complement) != ixs.end() && ixs[complement] != i){
return vector<int> {i, ixs[complement]};
}
}
return vector<int> {};
}
};
/**
Approach 3: One-pass Hash Table
build and check for complement at the same time
**/
/**
Complexity Analysis:
Time complexity : O(n).
We traverse the list containing nn elements only once.
Each look up in the table costs only O(1) time.
Space complexity : O(n).
The extra space required depends on the number of items stored in the hash table, which stores at most nn elements.
**/
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
map<int, int> ixs;
for(int i = 0; i < nums.size(); i++){
int complement = target - nums[i];
if(ixs.find(complement) != ixs.end()){
return vector<int> {i, ixs[complement]};
}
ixs[nums[i]] = i;
}
return vector<int> {};
}
};