思路:首先,我们初始一个新的结点ans,由于第一个元素也可能重复,所以我们需要让ans成为新的头结点。然后我们开始遍历链表,如果当前位置的结点cur满足cur.next==cur.next.next,那么我们记录cur.next的值x,然后遍历链表,去删除后续所有为x的结点。如果cur.next!=cur.next.next,则cur.next是不重复的元素,我没呢让cur = cur.next;重复上面的操作,直到链表结束。最后记得让ans = ans->next.因为我们初始化的那个结点,在最初的链表中是不存在的。
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
if (!head) {
return head;
}
ListNode* ans = new ListNode(0, head);
ListNode* cur = ans;
while (cur->next && cur->next->next) {
if (cur->next->val == cur->next->next->val) {
int x = cur->next->val;
while (cur->next && cur->next->val == x) {
cur->next = cur->next->next;
}
}
else {
cur = cur->next;
}
}
return ans->next;
}
};
思路:首先,由于题目要求三元组不能重复,所以我们可以对数组进行排序,然后从小到大一次去暴力求解a,b,c。这个时候仍然有可能重复,因为元素有重复的情况。因此我们每次遍历时都要保证与之前的元素不相等。三个for循环直接暴力求解。这个显然不是很好的选择,时间复杂度太大了。进一步,由于我们要找的是满足a+b+c=0的三个值,所以当我们确定了a的值以后,问题就退化为两数之和的问题了,这个时候我们可以使用双指针法来解决问题。关于两数之和问题,简单说一下,左右两个指针,如果两个数的和大于target,右边的指针右移一位;如果小于target,则左边的指针移动一位。整个算法的时间复杂度为O(N)。
所以三数之和的时间复杂度为O(N^2)
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> ans;
int n = nums.size();
if(n<=3){
return ans;
}
sort(nums.begin(),nums.end());
//由于我们选择时a<b<c,所以当a>0时,可以直接结束遍历
for(int ia = 0;ia<n;ia++){
//和上一次枚举的数不一样
if (ia > 0 && nums[ia] == nums[ia - 1]) {
continue;
}
//c从右边往左
int ic = n-1;
int target = -nums[ia];
for(int ib =ia+1;ib<n;ib++){
if(ib>ia+1&&nums[ib] == nums[ib-1]){
continue;
}
while(ib<ic&&nums[ib]+nums[ic]>target){
ic--;
}
if(ib>=ic){
break;
}
if(nums[ib]+nums[ic]==target){
ans.push_back({nums[ia],nums[ib],nums[ic]});
}
}
}
return ans;
}
};
思路:我们可以利用栈思想来解决这个问题,由于栈的先进后出原则,当我们遇到退格字符时,我们很方便的删去的前一个字符。最后我们统计两个栈内的字符是否一致即可.
class Solution {
public:
string made(string str) {
string ret;
for (int i =0;i<str.length();i++) {
if (str[i] != '#') {
//在尾部添加一个元素
ret.push_back(str[i]);
} else if (!ret.empty()) {
//删除最后一个元素,如果有的话
ret.pop_back();
}
}
return ret;
}
bool backspaceCompare(string s, string t) {
return made(s)==made(t);
}
};
思路:见图解:
由于first和second里面的集合都是不相交的,所以几种情况分析一下就可以很好的解决问题。
class Solution {
public:
vector<vector<int>> intervalIntersection(vector<vector<int>>& firstList, vector<vector<int>>& secondList) {
int n = firstList.size(), m = secondList.size();
vector<vector<int>> ans;
if(n == 0 || m == 0) return ans;
int i=0, j=0;
while(i<n && j<m){
// 求左右边界,有交集则加入ans
int left = max(firstList[i][0], secondList[j][0]);
int right = min(firstList[i][1], secondList[j][1]);
if(right >= left)
ans.push_back({left, right});
// 见图解很容易了解到,我们每次处理完以后都要讲右端点小的那个区间放弃,留下大的继续下一轮
if(firstList[i][1] < secondList[j][1])
i++;
else
j++;
}
return ans;
}
};