文章目录
链表中倒数第k个节点(快慢指针)
处理特殊情况:k大于链表数量,return {}
/**
* struct ListNode {
* int val;
* struct ListNode *next;
* ListNode(int x) : val(x), next(nullptr) {}
* };
*/
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param pHead ListNode类
* @param k int整型
* @return ListNode类
*/
ListNode* FindKthToTail(ListNode* pHead, int k) {
// write code here
auto p = pHead, q = pHead;
while(k && p != NULL) p = p->next,k --;
if(k > 0) return NULL; // k大于链表数量,return {}
while(p != NULL)
{
p = p->next;
q = q->next;
}
return q;
}
};
矩阵元素查找(二分)
类似二分的思想,从右上角开始枚举,每次干掉一行或者一列
class Solution {
public:
vector<int> findElement(vector<vector<int> > mat, int n, int m, int x) {
// write code here
int i =0, j = m - 1;
while(i < n && j >= 0)
{
if(mat[i][j] == x) return {
i,j};
else if(mat[i][j] > x) j --;
else if(mat[i][j] < x) i ++ ;
}
return {
};
}
};
最小编辑代价(DP)
72. 编辑距离进阶版
class Solution {
public:
/**
* min edit cost
* @param str1 string字符串 the string
* @param str2 string字符串 the string
* @param ic int整型 insert cost
* @param dc int整型 delete cost
* @param rc int整型 replace cost
* @return int整型
*/
int minEditCost(string str1, string str2, int ic, int dc, int rc) {
// write code here
int n = str1.size(), m = str2.size();
vector<vector<int>> f(n + 1,vector<int>(m + 1));
// 从A 变成 B 的代价
for(int i = 0;i <= n;i ++ ) f[i][0] = dc* i;
for(int i = 0;i <= m;i ++ ) f[0][i] = ic * i;
for(int i = 1;i <= n;i ++ )
for(int j = 1;j <= m;j ++ )
{
f[i][j] = min(f[i - 1][j] + dc,f[i][j - 1] + ic);
if(str1[i - 1] != str2[j - 1]) f[i][j] = min(f[i][j],f[i - 1][j - 1] + rc);
else f[i][j] = min(f[i][j],f[i - 1][j - 1]);
}
return f[n][m];
}
};
82. 删除排序链表中的重复元素 II(递推)
(线性扫描) O(n)
为了方便处理边界情况,我们定义一个虚拟元素 dummy 指向链表头节点。
然后从前往后扫描整个链表,每次扫描元素相同的一段,如果这段中的元素个数多于1个,则将整段元素直接删除。
时间复杂度分析:整个链表只扫描一遍,所以时间复杂度是 O(n)。
/**
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
class Solution {
public:
/**
*
* @param head ListNode类
* @return ListNode类
*/
ListNode* deleteDuplicates(ListNode* head) {
// write code here
ListNode* dummy = new ListNode(-1);
dummy->next = head; // 头结点可能会变,增加虚拟头结点
auto p = dummy ;
while(p->next)
{
auto q = p->next;
while(q && q->val == p->next->val) q = q->next;
if(p->next->next == q) p = p->next;
else p->next = q;
}
return dummy->next;
}
};
二叉树的最大路径和(递归)
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
int ans = INT_MIN;
int maxPathSum(TreeNode* root) {
dfs(root);
return ans;
}
// 返回从root向下走的最大值
int dfs(TreeNode* root)
{
if(!root) return 0;
auto left = dfs(root->left);
auto right = dfs(root->right);
ans = max(ans,left + root->val + right); // 枚举最高点,任何路径都有最高点
return max(0,root->val + max(left,right));
}
};
链表的奇偶重排(递推)
四个指针剥离原链表
/**
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* @param head ListNode类
* @return ListNode类
*/
ListNode* oddEvenList(ListNode* head) {
// write code here
if(head == NULL || head->next == NULL) return head;
auto odd_head = head,even_head = head->next, odd = head,even = head->next;
for(ListNode *p = head->next->next; p ;)
{
odd->next = p, odd = p, p = p->next;
if(p)
{
even->next = p,even = p, p = p->next;
}
}
odd->next = even_head,even->next = NULL;
return odd_head;
}
};
求路径(DP)
class Solution {
public:
/**
*
* @param m int整型
* @param n int整型
* @return int整型
*/
int uniquePaths(int m, int n) {
// write code here
vector<vector<int>> f(m + 1,vector<int>(n + 1));
f[1][1] = 1;
for(int i = 1;i <= m;i ++ )
for(int j = 1;j <= n;j ++ )
f[i][j] += f[i - 1][j] + f[i][j -1];
return f[m][n];
}
};
将字符串转化为整数(模拟)
注意int溢出处理
class Solution {
public:
int atoi(const char *str) {
if(*str=='\0') return 0;
const char* p =str;
while(*p==' ') ++p; // 去除空格
int sign=1;
if(*p == '-') sign = -1,p ++ ;
else if(*p == '+') p ++ ;
//long res=0;
int res = 0;
while(*p >= '0' && *p <= '9'){
//res = res * 10 + *p - '0';
int x = *p - '0';
// 判断溢出
if(sign > 0 && res > (INT_MAX - x) / 10) return INT_MAX;
if(sign < 0 && -res < (INT_MIN + x) / 10) return INT_MIN;
if(-res * 10 - x == INT_MIN) return INT_MIN;
res = res * 10 + x;
p ++ ;
}
return res*sign;
}
};
数字字符串转化为IP地址(爆搜)
class Solution {
public:
/**
*
* @param s string字符串
* @return string字符串vector
*/
vector<string> ans;
vector<string> restoreIpAddresses(string s) {
// write code here
dfs(s,0,0,"");
return ans;
}
// k表示截断的IP地址个数
void dfs(string &s,int u,int k,string path)
{
if(u == s.size())
{
if(k == 4){
path.pop_back(); // 去除最后一个'.';
ans.push_back(path);
}
return;
}
if(k == 4) return; // 剪枝
for(int i = u ,t = 0;i < s.size();i ++ )
{
if(i > u && s[u] == '0') break; // 有前导0
t = t * 10 + s[i] - '0';
if(t <= 255) dfs(s,i + 1,k + 1,path + to_string(t) + '.');
else break;
}
}
};
反转数字
C++里 负数取模为负数
class Solution {
public:
int reverse(int x) {
int res = 0; //
while(x){
int t = x % 10; // C++里 负数取模为负数
if(x > 0 && res > (INT_MAX - t) / 10) return 0; // 溢出判断
if(x < 0 && res < (INT_MIN - t) / 10) return 0;
res = res * 10 + t; // res * 10 + t > INT_MAX
// res * 10 + t < INT_MIN
x /= 10;
}
return res;
}
};