LeetCode—16(最接近的三数之和)
相对于上一题求三数之和为0,这道题让我们返回这个最接近给定值(target)的值,即我们要保证当前三数和跟给定值之间的差的绝对值最小,所以我们需要定义一个变量diff用来记录差的绝对值。
方法:还是先将数组排个序,然后遍历数组,思路跟上一题相似,都是先确定一个数,然后用两个指针left和right来滑动寻找另外两个数,每确定就求三数之和,然后算和给定值的差的绝对值存在newDiff中,比较更新即可。
class Solution {
public:
int threeSumClosest(vector<int>& nums, int target) {
int closest = nums[0] + nums[1] + nums[2];
int diff = abs(closest - target);
sort(nums.begin(), nums.end());
for (int i = 0; i < nums.size() - 2; ++i) {
int left = i + 1, right = nums.size() - 1;
while (left < right) {
int sum = nums[i] + nums[left] + nums[right];
int newDiff = abs(sum - target);
if (diff > newDiff) {
diff = newDiff;
closest = sum;
}
if (sum < target) ++left;
else --right;
}
}
return closest;
}
};
LeetCode—17(电话号码的字母组合)
递归的思想:(不是很了解,需详细了解)
C++代码:
class Solution {
public:
vector<string> letterCombinations(string digits) {
if (digits.empty()) return {};
vector<string> res;
string dict[] = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
letterCombinationsDFS(digits, dict, 0, "", res);
return res;
}
void letterCombinationsDFS(string digits, string dict[], int level, string out, vector<string> &res) {
if (level == digits.size()) {res.push_back(out); return;}
string str = dict[digits[level] - '0'];
for (int i = 0; i < str.size(); ++i) {
letterCombinationsDFS(digits, dict, level + 1, out + string(1, str[i]), res);
}
}
};
LeetCode—18(四数之和)
方法:在这里为了避免重复项,我们使用了STL中的set,其特点是不能有重复,如果新加入的数在set中原本就存在的话,插入操作就会失败,这样能很好的避免的重复项的存在。此题的O(n^3)解法的思路跟 3Sum 基本没啥区别,就是多加了一层for循环,其他的都一样。
C++代码:
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
set<vector<int>> res;
sort(nums.begin(),nums.end());
for (int i = 0; i < int(nums.size() - 3); ++i){
for(int j = i + 1; j < int(nums.size() -2); ++j){
if(j > i + 1 && nums[j] == nums[j - 1])continue;
int left = j + 1, right = nums.size() -1;
while (left < right){
int sum = nums[i] + nums[j] + nums[left] + nums[right];
if (sum == target){
vector<int> out{nums[i],nums[j],nums[left],nums[right]};
res.insert(out);
++left;--right;
}else if(sum < target) ++left;
else --right;
}
}
}
return vector<vector <int>>(res.begin(),res.end());
}
};
LeetCode—19(删除链表的倒数第N个节点)
方法:只允许一次遍历,我们需要两个指针来帮助我们。pre与cur指针。首先我们让cur指针向前走N步,由于本体N一定有效,因此若cur指向空,说明N为链表的长度,则需要移除的是首元素,此时返回head->next即可。若cur存在,我们再继续往下走,此时pre也跟着走,cur走S-N步到达最后一个元素,pre同样也走S-N步,即相当于倒数第N个。移除pre指向的前一个元素。修改指针跳过需要移除的元素实现即可。
C++解法:
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
if(!head->next) return NULL;
ListNode *pre = head,*cur = head;
for (int i = 0; i < n; ++i) cur = cur->next;
if(!cur) return head->next;//详细了解一下链表结构
while (cur->next){
cur = cur->next;
pre = pre->next;
}
pre->next = pre->next->next;//画图理解一下
return head;
}
};
LeetCode—20(有效的括号)
方法:需要用到栈,我们开始遍历输入字符串,如果当前字符串为左半边括号,则将其压入栈中,如果遇到右半边,取栈顶元素,若为空,直接返回false。 取出的栈顶元素若为对应的左半边括号,则继续循环,反之返回false。
C++代码:
class Solution {
public:
bool isValid(string s) {
stack<char> parentheses;
for (int i =0; i < s.size(); ++i){
if (s[i] == '(' || s[i] == '{' || s[i] == '[') parentheses.push(s[i]);
else{
if (parentheses.empty()) return false;
if (s[i] == ')' && parentheses.top() != '(') return false;
if (s[i] == ']' && parentheses.top() != '[') return false;
if (s[i] == '}' && parentheses.top() != '{') return false;
parentheses.pop();
}
}
return parentheses.empty();
}
};