编程

1、全排列

给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。

https://leetcode-cn.com/problems/permutations/solution/

class Solution {
public:void backtrack(vector<vector<int>>& res, vector<int>& output, int first, int len){// 所有数都填完了if (first == len) {res.emplace_back(output);return;}for (int i = first; i < len; ++i) {// 动态维护数组swap(output[i], output[first]);// 继续递归填下一个数backtrack(res, output, first + 1, len);// 撤销操作swap(output[i], output[first]);}}vector<vector<int>> permute(vector<int>& nums) {vector<vector<int> > res;backtrack(res, nums, 0, (int)nums.size());return res;}
};

2、螺旋矩阵

给你一个 mn 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。

https://leetcode-cn.com/problems/spiral-matrix/

解题思路:
这里的方法不需要记录已经走过的路径,所以执行用时和内存消耗都相对较小

1、首先设定上下左右边界
2、其次向右移动到最右,此时第一行因为已经使用过了,可以将其从图中删去,体现在代码中就是重新定义上边界
3、判断若重新定义后,上下边界交错,表明螺旋矩阵遍历结束,跳出循环,返回答案
4、若上下边界不交错,则遍历还未结束,接着向下向左向上移动,操作过程与第一,二步同理
5、不断循环以上步骤,直到某两条边界交错,跳出循环,返回答案

class Solution {
public:vector<int> spiralOrder(vector<vector<int>>& matrix) {vector <int> ans;if(matrix.empty()) return ans; //若数组为空,直接返回答案int u = 0; //赋值上下左右边界int d = matrix.size() - 1;int l = 0;int r = matrix[0].size() - 1;while(true){for(int i = l; i <= r; ++i) ans.push_back(matrix[u][i]); //向右移动直到最右if(++ u > d) break; //重新设定上边界,若上边界大于下边界,则遍历遍历完成,下同for(int i = u; i <= d; ++i) ans.push_back(matrix[i][r]); //向下if(-- r < l) break; //重新设定有边界for(int i = r; i >= l; --i) ans.push_back(matrix[d][i]); //向左if(-- d < u) break; //重新设定下边界for(int i = d; i >= u; --i) ans.push_back(matrix[i][l]); //向上if(++ l > r) break; //重新设定左边界}return ans;}
};

3、反转链表

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

https://leetcode-cn.com/problems/reverse-linked-list/

1、定义两个指针:pre和cur;pre在前 cur在后。
2、每次让 cur的next指向pre实现一次局部反转
3、局部反转完成之后,pre和 cur同时往前移动一个位置
4、循环上述过程,直至 cur到达链表尾部
class Solution {
public:ListNode* reverseList(ListNode* head) {ListNode* cur=head;ListNode* pre=nullptr;ListNode* temp=nullptr;while(cur!=nullptr){temp=cur->next;//记录当前节点的下一个节点cur->next=pre;//然后将当前节点指向prepre=cur;//pre和cur节点都前进一位cur=temp;}return pre;}
};

4、反转链表 II

给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。

https://leetcode-cn.com/problems/reverse-linked-list-ii/

class Solution {
public:ListNode* reverseBetween(ListNode* head, int left, int right) {// 定义一个dummyHead, 方便处理ListNode* dummy = new ListNode(0);      dummy->next = head;// 初始化指针ListNode* g = dummy;ListNode* p = dummy-> next;// 将指针移到相应的位置for(int i = 0; i < left -1; i++){g = g->next;p = p->next;}// 头插法插入节点for(int i = 0; i < right - left; i++){ListNode* remove = p->next;p->next = p->next->next;remove->next = g->next;g->next = remove;}return dummy->next;}
};

5、K 个一组翻转链表

https://leetcode-cn.com/problems/reverse-nodes-in-k-group/

class Solution {
public:ListNode* reverseKGroup(ListNode* head, int k) {
/*** Definition for singly-linked list.* public class ListNode {*     int val;*     ListNode next;*     ListNode(int x) { val = x; }* }*/if (head == nullptr || head->next == nullptr){return head;}//定义一个假的节点。ListNode* dummy=new ListNode(0);//假节点的next指向head。// dummy->1->2->3->4->5dummy->next=head;//初始化pre和end都指向dummy。pre指每次要翻转的链表的头结点的上一个节点。end指每次要翻转的链表的尾节点ListNode* pre=dummy;ListNode* end=dummy;while(end->next!=nullptr){//循环k次,找到需要翻转的链表的结尾,这里每次循环要判断end是否等于空,因为如果为空,end.next会报空指针异常。//dummy->1->2->3->4->5 若k为2,循环2次,end指向2for(int i=0;i<k&&end != nullptr;i++){end=end->next;}//如果end==null,即需要翻转的链表的节点数小于k,不执行翻转。if(end==nullptr){break;}//先记录下end.next,方便后面链接链表ListNode* next=end->next;//然后断开链表end->next=nullptr;//记录下要翻转链表的头节点ListNode* start=pre->next;//翻转链表,pre.next指向翻转后的链表。1->2 变成2->1。 dummy->2->1pre->next=reverse(start);//翻转后头节点变到最后。通过.next把断开的链表重新链接。start->next=next;//将pre换成下次要翻转的链表的头结点的上一个节点。即startpre=start;//翻转结束,将end置为下次要翻转的链表的头结点的上一个节点。即startend=start;}return dummy->next;}//链表翻转// 例子:   head: 1->2->3->4ListNode* reverse(ListNode* head) {//单链表为空或只有一个节点,直接返回原单链表if (head == nullptr || head->next == nullptr){return head;}//前一个节点指针ListNode* pre = nullptr;//当前节点指针ListNode* cur = head;//下一个节点指针ListNode* next = nullptr;while (cur != nullptr){next = cure->next;//next 指向下一个节点,保存当前节点后面的链表。cur->next=pre;//将当前节点next域指向前一个节点   null<-1<-2<-3<-4pre = cur;//pre指针向后移动。pre指向当前节点。cur = next;//cure指针向后移动。下一个节点变成当前节点}return preNode;}
};

6、岛屿数量

https://leetcode-cn.com/problems/number-of-islands/

给你一个由 ‘1’(陆地)和 ‘0’(水)组成的的二维网格,请你计算网格中岛屿的数量。岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。此外,你可以假设该网格的四条边均被水包围。

class Solution {
public:int numIslands(vector<vector<char>>& nums) {int res = 0;int m = nums.size(),n = nums[0].size();for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if (nums[i][j] == '1') {dfs(nums, i, j);res ++;}}}return res;}void dfs(vector<vector<char>>& nums, int i, int j) {if (i < 0 || j < 0 || i >= nums.size() || j >= nums[0].size() || nums[i][j] == '0')return;nums[i][j] = '0';dfs(nums, i + 1, j);dfs(nums, i, j + 1);dfs(nums, i - 1, j);dfs(nums, i, j - 1);}
};

7、最长回文串

给你一个字符串 s,找到 s 中最长的回文子串。

https://leetcode-cn.com/problems/longest-palindromic-substring/

class Solution {
public:string longestPalindrome(string s) {int n = s.size();if (n < 2) {return s;}int maxLen = 1;int begin = 0;// dp[i][j] 表示 s[i..j] 是否是回文串vector<vector<int>> dp(n, vector<int>(n));// 初始化:所有长度为 1 的子串都是回文串for (int i = 0; i < n; i++) {dp[i][i] = true;}// 递推开始// 先枚举子串长度for (int L = 2; L <= n; L++) {// 枚举左边界,左边界的上限设置可以宽松一些for (int i = 0; i < n; i++) {// 由 L 和 i 可以确定右边界,即 j - i + 1 = L 得int j = L + i - 1;// 如果右边界越界,就可以退出当前循环if (j >= n) {break;}if (s[i] != s[j]) {dp[i][j] = false;} else {if (j - i < 3) {dp[i][j] = true;} else {dp[i][j] = dp[i + 1][j - 1];//只有 s[i+1:j−1] 是回文串,并且 s 的第 i 和 j 个字母相同时,s[i:j]才会是回文串。}}// 只要 dp[i][L] == true 成立,就表示子串 s[i..L] 是回文,此时记录回文长度和起始位置if (dp[i][j] && j - i + 1 > maxLen) {maxLen = j - i + 1;begin = i;}}}return s.substr(begin, maxLen);}
};

8、数组中的第K个最大元素(快排65)

https://leetcode-cn.com/problems/kth-largest-element-in-an-array/

给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。

class Solution {
public:int findKthLargest(vector<int>& nums, int k) {// 优先队列可以用一个 for 循环解决哈。就是在 for 循环里面判断小顶堆里面的 size() 是否大于 k 个数,是的话就 poll() 出去;整个 for 循环结束之后剩下来的就是 k 个数的小顶堆。堆顶即第 k 大的数。// priority_queue<Type, Container, Functional>// Type 就是数据类型,Container 就是容器类型(Container必须是用数组实现的容器,比如vector,deque等等,但不能用 list。  STL里面默认用的是vector),Functional 就是比较的方式,当需要用自定义的数据类型时才需要传入这三个参数,使用基本数据类型时,只需要传入数据类型,默认是大顶堆priority_queue<int,vector<int>, greater<int> > heap;for (int num : nums) {heap.emplace(num);if (heap.size() > k) { heap.pop();   //此时k+1个}}return heap.top();}
};
快排之单边循环法
class Solution {public :int findKthLargest(vector<int>&nums, int k) {int len = nums.size();int left = 0;int right = len - 1;// 转换一下,第 k 大元素的下标是 len - kint target = len - k;while (true) {int index = partition(nums, left, right);if (index == target) {return nums[index];} else if (index < target) {left = index + 1;} else {right = index - 1;}}}* 对数组 nums 的子区间 [left..right] 执行 partition 操作,返回 nums[left] 排序以后应该在的位置* 在遍历过程中保持循环不变量的定义:int partition(vector<int>& nums, int left, int right) {int pivot = nums[left];int j = left;for (int i = left + 1; i <= right; i++) {if (nums[i] < pivot) {// j 的初值为 left,先右移,再交换,小于 pivot 的元素都被交换到前面j++;swap(nums, j, i);}}// 在之前遍历的过程中,满足 nums[left + 1..j] < pivot,并且 nums(j..i) >= pivotswap(nums, j, left);// 交换以后 nums[left..j - 1] < pivot, nums[j] = pivot, nums[j + 1..right] >= pivotreturn j;}void swap(vector<int>& nums, int index1, int index2) {int temp = nums[index1];nums[index1] = nums[index2];nums[index2] = temp;}
}
快排之双边循环法
lass Solution {vector<int> sortArray(vector<int>& nums) {quickSort(nums,0,nums.size()-1);return nums;}//快速排序主函数void quickSort(vector<int>& nums,int low,int high){//递归终止条件if(low >= high){return;}int mid = partition(nums,low,high);quickSort(nums,low,mid-1);quickSort(nums,mid+1,high);}//分割//每次找到基准元素对应的排序位置int partition(vector<int>& nums,int start,int end){int pivot = nums[start];int left = start;//不能从start+1开始,否则当只有两个数时,无论大小都会交换int right = end;while(left != right){while(left < right && nums[right] > pivot){//也可以写nums[right]>=pivot无影响right--;}while(left < right && nums[left] <= pivot){left++;}//结束两个子循环会有两种情况,只有left小于right时,才进行交换if(left < right){swap(nums,left,right);}}//此时跳出while循环,只可能是left等于right,不会有left>right的情况//接下来的交换和返回,写left或者right都行,因为两者相等swap(nums,start,left);return left;}void swap(vector<int>& nums,int i,int j){int temp = nums[i];nums[i] = nums[j];nums[j] = temp;}
}

9、有效的括号

https://leetcode-cn.com/problems/valid-parentheses/

给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符串是否有效。

有效字符串需满足:左括号必须用相同类型的右括号闭合。左括号必须以正确的顺序闭合。

class Solution {
public:bool isValid(string s) {unordered_map<char,int> m{{'(',1},{'[',2},{'{',3},{')',4},{']',5},{'}',6}};stack<char> st;bool istrue=true;for(char c:s){int flag=m[c];if(flag>=1&&flag<=3) st.push(c);else if(!st.empty()&&m[st.top()]==flag-3) st.pop();else {istrue=false;break;}}if(!st.empty()) istrue=false;return istrue}
};

10、无重复字符的最长子串

https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/

给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度

class Solution {
public:int lengthOfLongestSubstring(string s) {//    if(s.size()==0 ||s.size()==1) return s.size();哈希的有问题 aab//    if(s.size()==2 && s[0]==s[1]) return 1;//    if(s.size()==2 && s[0]!=s[1]) return 2;//    int a=0;//    for(int i=0;i<s.size();i++){//        unordered_map<char,int> dic;//        for(int j=i;j<s.size();j++){//            if(dic.find(s[j])!=dic.end()){//                if(j-i>a) a=j-i;//                break;//            }//             dic[s[j]]++;//        }//    }//    return a;if(s.size() == 0) return 0;unordered_set<char> lookup;int maxStr = 0;int left = 0;for(int i = 0; i < s.size(); i++){while (lookup.find(s[i]) != lookup.end()){lookup.erase(s[left]);//不断从左缩小窗口left ++;}maxStr = max(maxStr,i-left+1);lookup.insert(s[i]);}return maxStr;}
};

11、买卖股票的最佳时机

https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/)

给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。

你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。

返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。

class Solution {
public:int maxProfit(vector<int>& prices) {// int len = prices.size();// int res = 0;// // 前一天卖出可以获得的最大利润// int pre = 0;// for (int i = 1; i < len; i++) {//     // 利润差//     int diff = prices[i] - prices[i - 1];//    // 状态转移方程:第i天卖出可以获得的最大利润 = 第i-1天卖出的最大利润 + 利润差//     pre = max(pre + diff, 0);//     res = max(res, pre);// }// return res;// 动态规划。空间复杂度为O1,时间复杂度为On// 标记一个买入股票的日子的股价记作left,然后尝试在某一天卖出股票,策略如下:// 如果这一天的股价高于left,则可以考虑卖出股票,利润暂存到res里。// 如果这一天的股价小于等于left,则应该选择这一天作为买入股票的日子,此时的暂存的利润要么是0,要么是之前暂存的值。int left = 10000000;int res = 0;for(int i : prices){if(left >= i){left = i;}else if(left < i){res = max(i-left,res);}}return res;}
};

12、相交链表

https://leetcode-cn.com/problems/intersection-of-two-linked-lists/

给你两个单链表的头节点 headAheadB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null

class Solution {
public:ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {ListNode *node1 = headA;ListNode *node2 = headB;while (node1 != node2) {node1 = (node1 != NULL) ? node1->next : headB;//巧妙:是判断(node1 != NULL) ?,而不是(node1-next != NULL) ?  这样不会陷入死循环,比如在B的最后一个节点,node1 != NULL,但是node1->next 为Null,然后赋个node1,而下一步同样node2也走到了A的最后一个节点,所以node2也=Null,所以下一次while的判断不成立,跳出循环,相当于指向了同一个相同的节点Null(死亡),两个人都走了L1+L2的长度,所以最后到终点的时间也相同,不会出现死循环。用(node1-next != NULL) ?  会导致node永远不会指向nullnode2 = (node2 != NULL) ? node2->next : headA;}return node1;// 两个链表长度分别为L1+C、L2+C, C为公共部分的长度,第一个人走了L1+C步后,回到第二个人起点走L2步;第2个人走了L2+C步后,回到第一个人起点走L1步。 当两个人走的步数都为L1+L2+C时就两个家伙就相遇相爱了// 你变成我,走过我走过的路。我变成你,走过你走过的路。然后我们便相遇了}
};

13、两数之和

https://leetcode-cn.com/problems/two-sum/

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出和为目标值 target 的那两个整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

class Solution {
public:vector<int> twoSum(vector<int>& nums, int target) {unordered_map<int,int> dic;for(int i=0;i<nums.size();++i){auto it=dic.find(target-nums[i]);if(it!=dic.end()) {return {i,it->second};}dic[nums[i]]=i;}return {};}
};

两数相加

https://leetcode-cn.com/problems/add-two-numbers/

给你两个非空的链表,表示两个非负的整数。它们每位数字都是按照逆序的方式存储的,并且每个节点只能存储 一位 数字。

请你将两个数相加,并以相同形式返回一个表示和的链表。

class Solution {
public:ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {ListNode* head=new ListNode(-1);//存放结果的链表ListNode* h=head;//移动指针int sum=0;//每个位的加和结果bool carry=false;//进位标志while(l1!=NULL||l2!=NULL){sum=0;if(l1!=NULL){sum+=l1->val;l1=l1->next;}if(l2!=NULL){sum+=l2->val;l2=l2->next;}if(carry)sum++;h->next=new ListNode(sum%10);h=h->next;carry=sum>=10?true:false;}if(carry)   //如果最后还有一位进位{h->next=new ListNode(1);}return head->next;}
};

14、三数之和

https://leetcode-cn.com/problems/3sum/

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。

class Solution { //排序,双指针
public:vector<vector<int>> threeSum(vector<int>& nums) {vector<vector<int>> ans;if (nums.size() < 3) return ans;sort(nums.begin(), nums.end());for (int i = 0; i < nums.size(); i++) {if (nums[i] > 0) return ans;// 去重if ( i > 0 && nums[i] == nums[i - 1]) {//为什么要大于0?,防止在i=0是判断出错continue;}int left = i + 1;int right = nums.size() - 1;while (left < right) {if(nums[left] + nums[right] + nums[i] > 0) {right--;} else if(nums[left] + nums[right] + nums[i] < 0){left++;} else {ans.push_back({nums[left], nums[right], nums[i]});while (right > left && nums[right] == nums[right - 1]) right--;  //去掉重复的的while (right > left && nums[left] == nums[left + 1]) left++;    left++;//前两个循环结束,是指向在重复元素的最后一位right--;}}}return ans;}
};

15、最大子序和

https://leetcode-cn.com/problems/maximum-subarray/

给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

class Solution {
public:// 动态规划int maxSubArray(vector<int>& nums) {//dp[i]表示nums中以nums[i]结尾的最大子序和vector<int> dp(nums.size());dp[0] = nums[0];int result = dp[0];for (int i = 1; i <nums.size(); i++){dp[i] = max(dp[i - 1] + nums[i], nums[i]);result = max(result, dp[i]);}return result;}// 贪心int maxSubArray(vector<int>& nums) {//类似寻找最大最小值的题目,初始值一定要定义成理论上的最小最大值int result = INT_MIN;int numsSize = int(nums.size());int sum = 0;for (int i = 0; i < numsSize; i++){sum += nums[i];result = max(result, sum);//如果sum < 0,重新开始找子序串if (sum < 0){sum = 0;}}return result;}
};

16、环形链表

https://leetcode-cn.com/problems/linked-list-cycle/

给定一个链表,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

如果链表中存在环,则返回 true 。 否则,返回 false 。

class Solution {
public:bool hasCycle(ListNode *head) {//当一个链表有环时,快慢指针都会陷入环中进行无限次移动,然后变成了追及问题。想象一下在操场跑步的场景,只要一直跑下去,快的总会追上慢的。当两个指针都进入环后,每轮移动使得慢指针到快指针的距离增加一,同时快指针到慢指针的距离也减少一,只要一直移动下去,快指针总会追上慢指针。ListNode *slow = head;ListNode *fast = head;while(fast != nullptr) {fast = fast->next;if(fast != nullptr) {fast = fast->next;}if(fast == slow) {return true;}slow = slow->next;}return false;//如果存在环,如何判断环的长度呢?方法是,快慢指针相遇后继续移动,直到第二次相遇。两次相遇间的移动次数即为环的长度。}
};
给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意,pos 仅仅是用于标识环的情况,并不会作为参数传递到函数中
class Solution {
public:ListNode *detectCycle(ListNode *head) {ListNode *slow=head,*fast=head;while(1){if(fast ==nullptr || fast->next ==nullptr) return nullptr;fast=fast->next->next;slow=slow->next;if(fast==slow){  //第一次相遇,这时fast走了2nb,slow走了nbfast=head;break;}}while(fast != slow){   //让fast和slow走a,这时他们在入环的第一个节点相遇,fast=fast->next;slow=slow->next;}return fast;}
};

17、合并两个有序链表

https://leetcode-cn.com/problems/merge-two-sorted-lists/

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

这道题可以使用递归实现,新链表也不需要构造新节点,下面列举递归三个要素
终止条件:两条链表分别名为 l1 和 l2,当 l1 为空或 l2 为空时结束
返回值:每一层调用都返回排序好的链表头
本级递归内容:如果l1的 val值更小,则将 l1->next 与排序好的链表头相接,l2 同理
O(m+n),m为l1的长度,n为 l2 的长度
class Solution {
public:ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {if (l1 == NULL) {return l2;}if (l2 == NULL) {return l1;}if (l1->val <= l2->val) {l1->next = mergeTwoLists(l1->next, l2);return l1;}l2->next = mergeTwoLists(l1, l2->next);return l2;}
};

18、二叉树的层序遍历

https://leetcode-cn.com/problems/binary-tree-level-order-traversal/

给你一个二叉树,请你返回其按 层序遍历 得到的节点值。(即逐层地,从左到右访问所有节点)

class Solution {
public:vector<vector<int>> levelOrder(TreeNode* root) {vector<vector<int>> res;queue<TreeNode*> queue;if (root != nullptr) queue.push(root);while (!queue.empty()) {int n = queue.size();  // 无法区分队列中的结点来自哪一层。因此,我们需要稍微修改一下代码,在每一层遍历开始前,先记录队列中的结点数量 n(也就是这一层的结点数量),然后一口气处理完这一层的 n 个结点。vector<int> level;for (int i = 0; i < n; ++i) {TreeNode* node = queue.front();queue.pop();level.push_back(node->val);if (node->left != nullptr) queue.push(node->left);if (node->right != nullptr) queue.push(node->right);}res.push_back(level);}return res;}
};

19、二叉树的锯齿形层序遍历

https://leetcode-cn.com/problems/binary-tree-zigzag-level-order-traversal/

给定一个二叉树,返回其节点值的锯齿形层序遍历。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。

class Solution {
public: // 解题思路:每层遍历塞到数组里,那每层的一维数组的值是固定的,所以只要往这层塞数据就可以了// 根据题意,每层从左往右,下层从右往左,所以每偶数层添加在后面,每奇数层插入在前面,递归即可void Sum(vector<vector<int>>& arr, TreeNode* root, int row){if(root == nullptr)return;if(arr.size()<= row)arr.push_back(vector<int>());if(row%2 == 0)arr[row].push_back(root->val);elsearr[row].insert(arr[row].begin(), root->val);Sum(arr, root->left, row+1);Sum(arr, root->right, row+1);}vector<vector<int>> zigzagLevelOrder(TreeNode* root) {vector<vector<int>> arr;Sum(arr, root, 0);return arr;}};

20、合并两个有序数组

https://leetcode-cn.com/problems/merge-sorted-array/

给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。

请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。

注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。

  1. 思路的重点一个是从后往前确定两组中该用哪个数字
  2. 另一个是结束条件以第二个数组全都插入进去为止
class Solution {
public:void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {int i = nums1.size() - 1;m--;n--;while (n >= 0) {while (m >= 0 && nums1[m] > nums2[n]) {swap(nums1[i--], nums1[m--]);}swap(nums1[i--], nums2[n--]);}//     int i = nums1.size() - 1;//     --m;//     --n;//     while (n >= 0)//     {//         if(m >= 0 && nums1[m] > nums2[n])//         {//             nums1[i--] = nums1[m--];//         }//         else//         {//             nums1[i--] = nums2[n--];//         }//     }
}
};

21、二叉树的最近公共祖先

https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree/

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

class Solution {
public:TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {//1 当 left 和 right 同时为空 :说明 root 的左 / 右子树中都不包含 p,q ,返回 null ;//2 当 left 和 right 同时不为空 :说明 p,q 分列在 root 的 异侧 (分别在 左 / 右子树),因此 root为最近公共祖先,返回  root ;//3 当 left为空 ,right 不为空 :p,q都不在 root的左子树中,直接返回 right。具体可分为两种情况://    p,q 其中一个在 root 的 右子树 中,此时 right 指向 p(假设为 p);//    p,q 两节点都在 root 的 右子树 中,此时的 right 指向 最近公共祖先节点 ;//4 当 left 不为空 , right 为空 :与情况 3. 同理;if(root == nullptr || root == p || root == q) return root;TreeNode *left = lowestCommonAncestor(root->left, p, q);TreeNode *right = lowestCommonAncestor(root->right, p, q);if(left == nullptr && right == nullptr) return nullptr; // 1.if(left == nullptr) return right;// 3.if(right == nullptr) return left;// 4.return root;// 2. if(left != null and right != null)}
};

22、颜色填充

红,绿,蓝三种颜色,各自n个,相邻不能一样(首位不能一样),求填充方法数

对于我们可以选择红绿蓝三种颜色,我们可以将它们看成 0, 1, 2。这样一来,一种涂色方案就对应着一个长度为 m 的三进制数,其十进制的范围为 [0, 3^m)。

我们可以枚举 [0, 3^m)数,将其转换为长度为 m 的三进制串,再判断其是否满足任意相邻的两个数位均不相同即可。

int main() {unordered_map<int, vector<int>> valid;int m = 3;// 在 [0, 3^m) 范围内枚举满足要求的 maskint mask_end = pow(3,3);for (int mask = 0; mask < mask_end; ++mask) {vector<int> color;int mm = mask;for (int i = 0; i < m; ++i) {color.push_back(mm % 3);mm /= 3;}bool check = true;for (int i = 0; i < m - 1; ++i) {if (color[i] == color[i + 1]) {check = false;break;}}if (check) {valid[mask] = move(color);}}cout << valid.size();return 0;
}

23、搜索旋转排序数组

https://leetcode-cn.com/problems/search-in-rotated-sorted-array/

整数数组 nums 按升序排列,数组中的值 互不相同 。

在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k+1], …, nums[n-1], nums[0], nums[1], …, nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2] 。

给你 旋转后 的数组 nums 和一个整数 target ,如果 nums 中存在这个目标值 target ,则返回它的下标,否则返回 -1 。

class Solution {
public:int search(vector<int>& nums, int target) {if(nums.size()==0){return -1;}int left=0,right=nums.size()-1;while(left+1<right){int mid=left+(right-left)/2;if(nums[mid]==target){return mid;}if(nums[left]<nums[mid]){if((nums[mid]>=target)&&(target>=nums[left])){right=mid;}else {left=mid;}}if(nums[right]>nums[mid]){if((nums[mid]<=target)&&(target<=nums[right])){left=mid;}else{right=mid;}}}if (nums[left] == target ){return left;} if(nums[right] == target) {return right;}return -1;}
};

24、x的平方根

给你一个非负整数 x ,计算并返回 x算术平方根

由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3LqCGAbo-1649167843204)(C:\Users\hgx\AppData\Roaming\Typora\typora-user-images\image-20211012143335307.png)]

class Solution {
public:int mySqrt(int x) {if (x == 0) {return 0;}int ans = exp(0.5 * log(x));return ((long long)(ans + 1) * (ans + 1) <= x ? ans + 1 : ans);}
};
二分查找
class Solution {
public:int mySqrt(int x) {int l = 0, r = x, ans = -1;while (l <= r) {int mid = l + (r - l) / 2;if ((long long)mid * mid <= x) {ans = mid;l = mid + 1;} else {r = mid - 1;}}return ans;}
};
class Solution {
public:int s;int mySqrt(int x) {s=x;if(x==0) return 0;return ((int)(sqrts(x)));}double sqrts(double x){double res = (x + s / x) / 2;if (res == x) {return x;} else {return sqrts(res);}}
};

25、链表中倒数第k个节点

https://leetcode-cn.com/problems/lian-biao-zhong-dao-shu-di-kge-jie-dian-lcof/

输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。

class Solution {
public:ListNode* getKthFromEnd(ListNode* head, int k) {ListNode *fast = head, *slow = head;for(int i = 0; i < k; i++) {if(fast == nullptr) return nullptr;fast = fast->next;}while(fast != nullptr) {fast = fast->next;slow = slow->next;}return slow;}
};

26、删除链表的倒数第 k 个节点

https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/

class Solution {
public:ListNode* removeNthFromEnd(ListNode* head, int n) {ListNode* dummyHead = new ListNode(0);dummyHead->next = head;    //等同于ListNode* dummy = new ListNode(0, head);ListNode* p = dummyHead;ListNode* q = dummyHead;for( int i = 0 ; i < n + 1 ; i ++ ){q = q->next;}while(q){p = p->next;q = q->next;}ListNode* delNode = p->next;p->next = delNode->next;delete delNode;ListNode* retNode = dummyHead->next;delete dummyHead;return retNode;}
};

常见面试编程题c++相关推荐

  1. java校招面试题_java校招面试编程题及答案.docx

    java校招面试编程题及答案 java校招面试编程题及答案 Java集合框架为Java编程语言的基础,也是Java面试中很重要的一个知识点.这里,我列出了一些关于Java集合的重要问题和答案. 集合框 ...

  2. java常见笔试编程题(一)

    java常见笔试编程题(一) 编写一个截取字符串的函数,输入为一个字符串和字节数,输出为按字节截取的字符串.但是要保证汉字不被截半个,例如"人abc",应该截为"人ab& ...

  3. c语言面试编程笔试题,C语言面试编程题

    C语言面试编程题 发布时间:2021-04-10 在C语言中,输入和输出是经由标准库中的一组函数来实现的.在ANSI/ISO C中,这些函数被定义在头文件;中.下面就由第一范文网小编为大家介绍一下C语 ...

  4. 面试编程题胡萝卜切片

    面试编程题胡萝卜切片 记录一下python实现 class Solution:def last_carrot_weight(self, carrots: list):while True:a=[]fo ...

  5. 小米一面经验分享,面试编程题

    第一次面试大厂,其实挺紧张的. 本人应届生,面试岗位是小米的嵌入式工程师 一面是技术基础面流程:自我介绍 - 面试官自我介绍 - 根据简历内容提问 - 手撕代码 面试官人很好,每次提问之后,都会再阐述 ...

  6. 《面试》 --阿里巴巴数据分析岗面试编程题解析

    昨天做阿里非研发岗编程题,虽不是很难,但还是因为个人原因调试失败,特此今日复盘,希望能帮助大家提高. 第一题 选择出行方式,ofo是每1.5公里1元,不足1.5公里的按1.5计算 永安行是使用时间,每 ...

  7. 魔法王国java_网易2018校园招聘面试编程题真题与参考答案集合

    [编程题] 魔法币 小易准备去魔法王国采购魔法神器,购买魔法神器需要使用魔法币,但是小易现在一枚魔法币都没有,但是小易有两台魔法机器可以通过投入x(x可以为0)个魔法币产生更多的魔法币. 魔法机器1: ...

  8. 《面试编程题真题合集(一)——网易2019校园招聘真题题解》

    题目来源:牛客网https://www.nowcoder.com/contestRoom?filter=2&page=1 一.魔法币问题 题目描述: 小易准备去魔法王国采购魔法神器,购买魔法神 ...

  9. python二级编程题百度文库_Python自动化面试常见的编程题及答案

    前言 随着行业的发展,编程能力逐渐成为软件测试从业人员的一项基本能力.因此在笔试和面试中常常会有一定量的编码题,主要考察以下几点. 基本编码能力及思维逻辑 基本数据结构(顺序表.链表.队列.栈.二叉树 ...

最新文章

  1. css加载会造成阻塞吗
  2. mysql emma 使用教材_emma的使用
  3. 三年从前端小工到架构-知乎 Live 学习整理
  4. 黑马程序员Linux系统开发视频之线程共享资源与非共享资源
  5. 算法练习day10——190328(二叉树的先序、 中序、 后序遍历, 包括递归方式和非递归方式、找到一个节点的后继节点、二叉树的序列化和反序列化)
  6. 用一辈子去领悟的生活经典[转帖]
  7. MYSQL快速导入大量数据
  8. 类的声明、成员的访问控制和对象
  9. 还在担心漏测吗?快来使用jacoco统计下代码覆盖率
  10. java基础教程:集合概述(27)
  11. 9行python代码批量修改window屏保图文件
  12. 计算机win加r,快捷键win+r是什么意思_打开运行快捷键win+r怎么按
  13. NotePad++ HexEditor.dll下载地址,32位,64位
  14. Python 基础起步 (七) 初识字典 Dictionary(绝命毒师前传)
  15. java.lang.IncompatibleClassChangeError 常见错误
  16. Java:新世纪时代的召唤--启航
  17. php mysql md5加密_php 用户密码MD5加密存入数据库问题//
  18. Linux_进程控制(创建进程,等待进程,进程终止)
  19. red hat 系统下载
  20. 计算机导论sql试题,数据库SQL语句练习题

热门文章

  1. linux命令(3):pwd命令
  2. 安装lightgbm报错Filelt ornoiEtnw Cuild nt find moble ‘Try usi ng the fil. pth with constowctor synta.
  3. ubuntu kylin 优麒麟中的录屏软件
  4. windows下VMware安装CentOS7
  5. ​搜狐大量员工遭遇“工资补助”诈骗;​腾讯客服回应“借钱就能避免微信号被封”;TypeScript 4.7发布|极客头条
  6. 名编辑电子杂志大师教程 | 名编辑电子杂志输出PDF文件
  7. java调用DLL(指纹采集机器例子)
  8. PE结构详解(64位和32位的差别)
  9. 计算机软件著作权可否转让,计算机软件著作权能转让吗
  10. Easyx图形编程-课堂练习