数据结构和算法
1、给定一个整数数组和一个整数 k,你需要找到该数组中和为 k 的连续的子数组的个数。
示例 1 :
输入:nums = [1,1,1], k = 2
输出: 2 , [1,1] 与 [1,1] 为两种不同的情况。
说明 :
数组的长度为 [1, 20,000]。
数组中元素的范围是 [-1000, 1000] ,且整数 k 的范围是 [-1e7, 1e7]。
1 2 3 4 5 | 给定整数数组 A 和 常数 m, 输出 A 中满足数列和为 m 的连续子序列个数 示例 输入: A = [1,2,3], m=3 输出: 2 |
思路:
1)累计求和,双层遍历求差是否为目标值,得到满足条件的个数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | class Solution { public : int subarraySum(vector< int >& nums, int k) { int n=nums.size(); vector< int > sum(n+1,0); for ( int i=1;i<=n;i++) sum[i]=sum[i-1]+nums[i-1]; int count=0; for ( int i=0;i<n;i++){ for ( int j=i;j<n;j++){ if (sum[j+1]-sum[i]==k) count+=1; } } return count; } }; |
2)哈希表思路,累计求和放在哈希表中,然后看求和的数和目标值的差是否在哈希表中存在,以及存在的个数,以此求和得到满足条件的个数,初始化hash[0]=1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | class Solution { public : int subarraySum(vector< int >& nums, int k) { unordered_map< int , int > hash; int sum = 0, ans = 0; hash[0] = 1; for ( int num : nums) { sum += num; ans += hash[sum - k]; hash[sum]++; } return ans; } }; |
2、反转链表
示例:
输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL
进阶:
你可以迭代或递归地反转链表。你能否用两种方法解决这道题?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | // 递归方式 class Solution { public : ListNode* reverseList(ListNode* head) { //结束条件 if (head == NULL || head->next == NULL) return head; //递归反转剩下的元素 ListNode* rev = reverseList(head->next); //头节点变为最后一个节点 head->next->next = head; //头节点指针设置为空 head->next = NULL; return rev; } }; |
2)非递归方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | class Solution { public : ListNode* reverseList(ListNode* head) { if (head==NULL || head->next == NULL){ return head; } //前面一个节点 ListNode* pre = nullptr ; //当前节点 ListNode* cur = head; while (cur != nullptr ) { //指针先向后遍历 ListNode* tmp = cur->next; //改变指针指向 cur->next = pre; //前面一个节点变为当前节点、当前节点变为后面的节点 pre = cur; cur = tmp; } return pre; } }; |
3、给你一个链表数组,每个链表都已经按升序排列。
请你将所有链表合并到一个升序链表中,返回合并后的链表。
示例 1:
输入:lists = [[1,4,5],[1,3,4],[2,6]]
输出:[1,1,2,3,4,4,5,6]
解释:链表数组如下:
[
1->4->5,
1->3->4,
2->6
]
将它们合并到一个有序链表中得到。
1->1->2->3->4->4->5->6
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | /** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode() : val(0), next(nullptr) {} * ListNode(int x) : val(x), next(nullptr) {} * ListNode(int x, ListNode *next) : val(x), next(next) {} * }; */ class Solution { public : ListNode* merge(ListNode* l1, ListNode* l2){ //合并L1,L2两个有序链表 if (!l1) return l2; if (!l2) return l1; if (l1->val < l2->val){ l1->next = merge(l1->next, l2); return l1; } else { l2->next = merge(l1, l2->next); return l2; } } ListNode* mergeKLists(vector<ListNode*>& lists) { int interval = 1; int len = lists.size(); if (len==1){ return lists[0]; } if (len==0){ return nullptr ; } while (interval<len){ for ( int i=0;i<len-interval;){ lists[i]=merge(lists[i],lists[i+interval]); i=i+2*interval; } interval = interval*2; } return lists[0]; } }; |
4、给你一个只包含 '(' 和 ')' 的字符串,找出最长有效(格式正确且连续)括号子串的长度。
示例 1:
输入:s = "(()"
输出:2
解释:最长有效括号子串是 "()"
示例 2:
输入:s = ")()())"
输出:4
解释:最长有效括号子串是 "()()"
示例 3:
输入:s = ""
输出:0
两种思路:
1)用栈实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | class Solution { public : int longestValidParentheses(string s) { int maxLen = 0; stack< int > st; st.push(-1); for ( int i = 0; i < s.size(); i++) { char c = s[i]; if (c == '(' ) { // 左括号的索引,入栈 st.push(i); } else { // 遍历到右括号, 栈顶的左括号被匹配,出栈 st.pop(); if (st.size()!=0) { // 栈未空,计算有效连续长度 int curMaxLen = i - st.top(); // 挑战最大值 maxLen = max(maxLen, curMaxLen); } else { // 栈空了,入栈充当参照 st.push(i); } } } return maxLen; } }; |
2)动态规划思路:求最值问题
5、我们把数组 A 中符合下列属性的任意连续子数组 B 称为 “山脉”:
B.length >= 3
存在 0 < i < B.length - 1 使得 B[0] < B[1] < ... B[i-1] < B[i] > B[i+1] > ... > B[B.length - 1]
(注意:B 可以是 A 的任意子数组,包括整个数组 A。)
给出一个整数数组 A,返回最长 “山脉” 的长度。
如果不含有 “山脉” 则返回 0。
示例 1:
输入:[2,1,4,7,3,2,5]
输出:5
解释:最长的 “山脉” 是 [1,4,7,3,2],长度为 5。
示例 2:
输入:[2,2,2]
输出:0
解释:不含 “山脉”。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | class Solution { public : int longestMountain(vector< int >& arr) { int len = arr.size(); vector< int > dp(len,0); for ( int i=1;i<len;i++){ if (arr[i]>arr[i-1]&&dp[i-1]==0){ dp[i]=max(dp[i-1]+2,0); } else if (arr[i]>arr[i-1]){ dp[i]=max(dp[i-1]+1,0); } } vector< int > dp2(len,0); for ( int i=len-1;i>0;i--){ if (arr[i]<arr[i-1]&&dp2[i]==0){ dp2[i-1]=max(dp2[i]+2,dp2[i]); } else if (arr[i]<arr[i-1]){ dp2[i-1]=max(dp2[i]+1,dp2[i]); } } int res = 0; if (dp[len-1]==len||dp2[0]==len){ return 0; } for ( int i=0;i<len;i++){ if (dp[i]>=2&&dp2[i]>=2 && (dp[i]+dp2[i]>res)){ res = dp[i]+dp2[i]-1; } } return res; } }; |
6、单词搜索(leetcode 212,79)
给定一个 m x n 二维字符网格 board 和一个单词(字符串)列表 words,找出所有同时在二维网格和字典中出现的单词。
单词必须按照字母顺序,通过 相邻的单元格 内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母在一个单词中不允许被重复使用。
思路:回溯算法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | class Solution { public : int h; int w; vector<string> findWords(vector<vector< char >>& board, vector<string>& words) { vector<string> res; h = board.size(); w = board[0].size(); for ( int k=0;k<words.size();k++){ for ( int i = 0; i < h; i++){ for ( int j = 0; j < w; ++j){ //尝试从每一个字母开始回溯 if (searchexist(board, words[k], 0, i, j)){ res.push_back(words[k]); i = h; j = w; } } } } return res; } int searchexist(vector<vector< char >>& board, string &word, int n, int x, int y){ if (x < 0 || x > h-1 || y < 0 || y > w-1 || word[n] != board[x][y]) return 0; //达成要求返回1 if (n == word.length()-1) return 1; //将用过的保存起来 char temp = board[x][y]; board[x][y] = 0; //四个方回溯 int flag = searchexist(board, word, n+1, x+1, y) ||searchexist(board, word, n+1, x-1, y) ||searchexist(board, word, n+1, x, y+1) ||searchexist(board, word, n+1, x, y-1); //回溯失败,将其重置 board[x][y] = temp; return flag; } }; |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架