中间有一段时间没有完全适应工作节奏,所以刷题和其他的一些计划也搁置了,以后争取每天都做少量题练手。
今天是数组的中等/难题+链表的简单题。
我个人的思路整理:(题目代码在后面)
LC16 最接近的三数之和 中等
给出含有n个整数的数组s,找出s中和加起来的和最接近给定的目标值的三个整数。返回这三个整数的和。你可以假设每个输入都只有唯一解。
例如,给定的整数 S = {-1 2 1 -4}, 目标值 = 1.↵↵ 最接近目标值的和为 2. (-1 + 2 + 1 = 2).
class Solution {public: int threeSumClosest(vector<int> &num, int target) { int res=0; int d=INT_MAX; sort(num.begin(),num.end()); for(int i=0;i int left=i+1; int right=num.size()-1; while(left int sum=num[i]+num[left]+num[right]; if(d>abs(sum-target)){ res=sum; d=abs(sum-target); } if(sum==target) return target; else if(sum>target) right--; else left++; } } return res; }};
LC31 下一个排列 中等
实现函数next permutation(下一个排列):将排列中的数字重新排列成字典序中的下一个更大的排列。将排列中的数字重新排列成字典序中的下一个更大的排列。
如果不存在这样的排列,则将其排列为字典序最小的排列(升序排列)
需要使用原地算法来解决这个问题,不能申请额外的内存空间
下面有机组样例,左边是输入的数据,右边是输出的答案
1,2,3→1,3,2
3,2,1→1,2,3
1,1,5→1,5,1
class Solution {public: void nextPermutation(vector<int> &num) { /* * 目的:下一个排列 * 方法: * 例如:1 2 3 7 6 5 1 * 1.从后往前找到不满足递增排序的点 * 2.如果不存在这样的点证明数组是非递增的,直接reverse,然后返回即可 * 3.如果找到,例如上例中的7,则重新从后往前寻找大于3的第一个数,即5 * 4.交换3和5的位置,然后将后面的数组升序排列,即可得到结果 */ int n = num.size(); if(n<=1) return; int i = n-1; while((i>0) && (num[i] <= num[i-1])){ i--; } if(i==0){ reverse(num.begin(), num.end()); } else{ int j = num.size()-1; while(num[j]<=num[i-1]) j--; swap(num[i-1], num[j]); sort(num.begin()+i,num.end()); //后面的全部排序 } }};
LC80 删除数组中重复元素2 中等
继续思考题目"Remove Duplicates":
如果数组中元素最多允许重复两次呢?
例如:
给出有序数组 A =[1,1,1,2,2,3],
你给出的函数应该返回length =5, A 变为[1,1,2,2,3]
class Solution {public: int removeDuplicates(int A[], int n) { if(n<=2) return n; int index=2; for(int i=2;i if(A[i]!=A[index-2]) A[index++]=A[i]; } return index; }};
LC88 合并两个有序数组 简单
给出两个有序的整数数组A和B,请将数组B合并到数组A中,变成一个有序的数组
注意:可以假设A数组有足够的空间存放B数组的元素,A和B中初始的元素数目分别为m和n
class Solution {public: void merge(int A[], int m, int B[], int n) { //这就是归并排序中合拼的部分 //由于不让new新数组(会爆) //所以将大的放在A数组的最右边 从右边往左边放 //如果A穷尽,把B元素依次放进A的前几个位置,如果B穷尽,正好结束。 //边界:有一个数组为空 if(m==0){ for (int i = 0; i < n; i++){ A[i] = B[i]; } } if(n==0) return; //归并 int i = m-1; int j = n-1; int cnt = m+n-1; while(i>=0 && j>=0){ if (A[i]>=B[j]){ A[cnt]=A[i]; cnt--; i--; } else{ A[cnt]=B[j]; cnt--; j--; } } //如果B先穷尽了,不要紧 //如果A先穷尽了 if (i==-1){ while(j>=0){ A[j] = B[j]; j--; } } }};
LC128 最长连续子序列 困难
给定一个无序的整数类型数组,求最长的连续元素序列的长度。
例如:
给出的数组为[100, 4, 200, 1, 3, 2],
最长的连续元素序列为[1, 2, 3, 4]. 返回这个序列的长度:4
你需要给出时间复杂度在O(n)之内的算法
class Solution {public: int longestConsecutive(vector<int>& nums) { unordered_set<int> st; for(int n: nums) st.insert(n); int ans = 0; for(int i: st){ // 假如一个数在哈希表中存在比他小的,那么它不是可以作为开头的数字 if(i != INT_MIN && st.count(i-1)){ continue; } // 开始计数 int cnt = 1; while(i!=INT_MAX && st.count(i+1)){ cnt ++; i++; } ans = max(ans, cnt); } return ans; }};
LC141 环形链表 简单
判断给定的链表中是否有环
扩展:
你能给出不利用额外空间的解法么?
class Solution {public: bool hasCycle(ListNode *head) { //用一快一慢指针,开始两个指针都指向链表头部。 //慢指针每次向前走一步,快指针每次向前走两步。 //如果有环,则两个指针最终一定会相遇。这种方法无须额外的空间。 ListNode * fast = head; ListNode * slow = head; //务必注意判断链表空、链表尾!!! while (fast != NULL && fast->next != NULL){ slow = slow->next; fast = fast->next->next; if (slow == fast) return true; } return false; }};
LC83 删除链表中重复元素 简单
删除给出链表中的重复元素(链表中元素从小到大有序),使链表中的所有元素都只出现一次
例如:
给出的链表为1->1->2,返回1->2.
给出的链表为1->1->2->3->3,返回1->2->3.
class Solution {public: /** * * @param head ListNode类 * @return ListNode类 */ ListNode* deleteDuplicates(ListNode* head) { // write code here ListNode* p = head; // 一定注意判空!判断是否是尾! while(p!=NULL){ while( p->next !=NULL && p->val == p->next->val){ //如果相邻两元素相同 p->next = p->next->next; //那么就删除这个元素 } p = p->next; //指针后移一位 } return head; }};
剑指25 合并两个有序链表 简单
将两个有序的链表合并为一个新链表,要求新的链表是通过拼接两个链表的节点来生成的。
/** * struct ListNode { * int val; * struct ListNode *next; * }; */class Solution {public: /** * * @param l1 ListNode类 * @param l2 ListNode类 * @return ListNode类 */ ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) { // write code here //每次选择剩下的节点中最小的,而最小的一定是链表1或者链表2剩下部分的第一个。 //用递归大法 if (l1 == NULL) return l2; if (l2 == NULL) return l1; ListNode* head; //建立一个新链表的头结点 if (l1-> val < l2-> val){ head = l1; head-> next = mergeTwoLists(l1->next, l2); } else{ head = l2; head-> next = mergeTwoLists(l1, l2->next); } return head; }};