目录
16. 最接近的三数之和
17. 电话号码的字母组合
18. 四数之和
19. 删除链表的倒数第N个节点
20. 有效的括号
16. 最接近的三数之和
题目描述
给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target最接近。返回这三个数的和。假定每组输入只存在唯一答案。
示例:
输入:nums = [-1,2,1,-4], target = 1
输出:2
解释:与 target 最接近的和是 2 (-1 + 2 +1 = 2) 。
提示:
3 <= nums.length <= 10^3
-10^3 <= nums[i] <= 10^3
-10^4 <= target <=10^4
思路
排序 + 双指针
本题目因为要计算三个数,如果靠暴力枚举的话时间复杂度会到 O(n^3)需要降低时间复杂度 首先进行数组排序,时间复杂度
O(nlogn) 在数组 nums 中,进行遍历,每遍历一个值利用其下标i,形成一个固定值 nums[i] 再使用前指针指向 start
= i + 1 处,后指针指向 end = nums.length - 1 处,也就是结尾处 根据 sum = nums[i] + nums[start] + nums[end] 的结果,判断 sum 与目标 target 的距离,如果更近则更新结果 ans 同时判断
sum 与 target 的大小关系,因为数组有序,如果 sum > target 则 end–1, 如果 sum < target 则
start+1,如果 sum == target 则说明距离为 0 直接返回结果 整个遍历过程,固定值为 n 次,双指针为 n
次,时间复杂度为 O(n^2) 总时间复杂度:O(nlogn) + O(n^2) = O(n^2)
c++代码
class Solution {
public:
int threeSumClosest(vector<int>& nums, int target) {
int ans = 1000000000;
sort(nums.begin(),nums.end());
int n = nums.size();
for(int i =0;i<nums.size();i++)
{
//if(i&&nums[i]==nums[i-1])continue;
for(int j =i+1,k=nums.size()-1;j<k;)
{
//if(j>i+1&&nums[j]==nums[j-1])
// continue;
int sum = nums[i]+nums[j]+nums[k];
if(sum==target)
return sum;
if(abs(sum-target)<abs(ans-target))
{
ans = sum;
}
if(sum>target)k--;
if(sum<target)j++;
}
}
return ans;
}
};
python 代码
class Solution(object):
def threeSumClosest(self, nums, target):
ans = 1e4
nums.sort()
n = len(nums)
for i in range(n):
if i != 0 and nums[i] == nums[i - 1]:
continue
j = i + 1
k = n - 1
while j < k:
num = nums[i] + nums[j] + nums[k]
if num == target:
return num
if abs(num - target) < abs(ans - target):
ans = num
if num > target:
k -= 1
if num < target:
j += 1
return ans
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
17. 电话号码的字母组合
题目描述
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。 给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
示例:
输入:“23”
输出:[“ad”, “ae”, “af”, “bd”, “be”, “bf”, “cd”, “ce”, “cf”].
思路
递归
可以通过手工或者循环的方式预处理每个数字可以代表哪些字母。 通过递归尝试拼接一个新字母。
递归到目标长度,将当前字母串加入到答案中。 注意,有可能数字串是空串,需要特判。
c++版
class Solution {
public:
string mp[10] = {"","","abc","def",
"ghi","jkl","mno",
"pqrs","tuv","wxyz"};
vector<string> ans;
vector<string> letterCombinations(string digits) {
if(digits.empty()) return ans;
dfs(digits, 0, "");
return ans;
}
void dfs(string digits,int u,string path)
{
if(u==digits.size())
ans.push_back(path);
else{
for(auto c:mp[digits[u]-'0'])
{
dfs(digits, u+1, path+c);
}
}
}
};
python 版本
class Solution(object):
def letterCombinations(self, digits):
mp = ["","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"]
ans = []
def dfs(strs, u, path):
if u == len(strs):
ans.append(path)
return
index = int(strs[u])
for c in mp[index]:
dfs(strs,u + 1, path + c)
if len(digits) == 0:
return ans
dfs(digits, 0, "")
return ans
"""
:type digits: str
:rtype: List[str]
"""
18. 四数之和
题目描述
给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a+ b + c + d 的值与 target 相等?找出所有满足条件且不重复的四元组。
注意: 答案中不可以包含重复的四元组。
示例:
给定数组 nums = [1, 0, -1, 0, -2, 2],和 target = 0。
满足要求的四元组集合为:
[ [-1, 0, 0, 1], [-2, -1, 1, 2], [-2, 0, 0, 2] ]
思路
排序+双指针
跟15题的解题思路一样,只不过这里要多循环一层
c++版
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int>> ans;
sort(nums.begin(),nums.end());
int n = nums.size();
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;//去掉重复元素
int k = j + 1;
int u = n - 1;
while(k < u){
int num = nums[i] + nums[j] + nums[k] + nums[u];
if(num > target){
while(k < u && nums[u] == nums[u - 1])u--;//去掉重复元素
u--;
}
else if(num < target) {
while(k < u && nums[k] == nums[k + 1])k++;//去掉重复元素
k++;
}
else{
ans.push_back({nums[i],nums[j],nums[k],nums[u]});
while(k < u && nums[u] == nums[u - 1])u--;//去掉重复元素
while(k < u && nums[k] == nums[k + 1])k++;//去掉重复元素
k++;
u--;
}
}
}
}
return ans;
}
};
python版
class Solution:
def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
ans = []
nums.sort()
n = len(nums)
for i in range(n - 3):
if i > 0 and nums[i] == nums[i - 1]:
continue
for j in range(i + 1, n - 2):
if j > i + 1 and nums[j] == nums[j - 1]:
continue
k = j + 1
u = n - 1
while(k < u):
num = nums[i] + nums[j] + nums[k] + nums[u]
if num > target:
while(k < u and nums[u] == nums[u - 1]):
u -= 1
u -= 1
elif num < target:
while(k < u and nums[k] == nums[k + 1]):
k += 1
k += 1
else:
ans.append([nums[i],nums[j],nums[k],nums[u]])
while(k < u and nums[k] == nums[k + 1]):
k += 1
while(k < u and nums[u] == nums[u - 1]):
u -= 1
k += 1
u -= 1
return ans
19. 删除链表的倒数第N个节点
题目描述
给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
示例:
给定一个链表: 1->2->3->4->5, 和 n = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.
说明:
给定的 n 保证是有效的。
进阶:
你能尝试使用一趟扫描实现吗?
思路
第一种做法:首先循环一遍得到长度L,知道长度后再循环一次得到答案
第二种做法:(快慢指针)我们可以使用两个指针而不是一个指针。第一个指针从列表的开头向前移动 n+1 步,而第二个指针将从列表的开头出发。
现在,这两个指针被 n 个结点分开。我们通过同时移动两个指针向前来保持这个恒定的间隔,直到第一个指针到达最后一个结点。
此时第二个指针将指向从最后一个结点数起的第 n 个结点。我们重新链接第二个指针所引用的结点的 next 指针指向该结点的下下个结点。
c++代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* a = new ListNode(-1);
a->next = head;
ListNode* p = a;
ListNode* q = a;
for(int i = 0; i <= n; i++)
p = p->next;
while(p != NULL){
q = q->next;
p = p->next;
}
q->next = q->next->next;
return a->next;
}
};
a = ListNode(-1)
a.next = head
p = a
q = a
for i in range(0, n + 1):
p = p.next
while(p):
p = p.next
q = q.next
q.next = q.next.next
return a.next
20. 有效的括号
题目描述
给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串,判断字符串是否有效。 有效字符串需满足:
左括号必须用相同类型的右括号闭合。 左括号必须以正确的顺序闭合。 注意空字符串可被认为是有效字符串。
示例 1:
输入: “()”
输出: true
示例 2:
输入: “()[]{}”
输出: true
示例 3:
输入: “(]”
输出: false
示例 4:
输入: “([)]”
输出: false
示例 5:
输入: “{[]}”
输出: true
思路
栈的应用,遍历字符串,如果当前字符为括号的左半边’(’, ‘[’, ‘{‘就加入到栈中去; 如果当前字符为括号的右半边’)’, ‘]’,
‘}’,则判断是否与栈中的字符匹配,如果匹配的话就出栈。 最后判断栈是否为空即可
c++版本
class Solution {
public:
bool isValid(string s) {
//char a[10010];
stack<char>a;
for(int i = 0; i < s.size(); i++){
if(s[i] == '}' &&!a.empty()&& a.top() == '{')
a.pop();
else if(s[i] == ']' &&!a.empty()&&a.top() == '[')
a.pop();
else if(s[i] == ')' &&!a.empty()&& a.top() == '(')
a.pop();
else a.push(s[i]); //a[++t] = s[i];
}
if(a.empty()) return true;
else return false;
}
};
python版本
class Solution(object):
def isValid(self, s):
stack = [""]
t = 0
for c in s:
if t > 0 and c == ')' and stack[t] == '(':
t -= 1
stack.pop()
elif t > 0 and c == '}' and stack[t] == '{':
t -= 1
stack.pop()
elif t > 0 and c == ']' and stack[t] == '[':
t -= 1
stack.pop()
else:
t += 1
stack.append(c)
return True if t == 0 else False
"""
:type s: str
:rtype: bool
"""