文章目录
top K问题(堆排,快排)
堆排O(nlogk)
class Solution {
public:
/**
* return topK string
* @param strings string字符串vector strings
* @param k int整型 the k
* @return string字符串vector<vector<>>
*/
vector<vector<string> > topKstrings(vector<string>& strings, int k) {
// write code here
map<string,int> hash;
for(auto &c : strings) hash[c] ++ ;
typedef pair<int,string > PIS;
priority_queue<PIS> q; // 默认大根堆,技巧:值加-即为小根堆
for(auto [s,v] : hash)
{
q.push({
-v,s});
if(q.size() > k) q.pop();
}
vector<vector<string> > res(k);
for(int i = k - 1;i >= 0;i -- )
{
auto t = q.top();
q.pop();
int cnt = -t.first;
string s = t.second;
cout << s <<' ' << cnt << endl;
res[i].push_back(s);
res[i].push_back(to_string(cnt));
}
return res;
}
};
快排 + 多关键字排序?(多关键字不会),O(n)
class Solution {
public:
/**
* return topK string
* @param strings string字符串vector strings
* @param k int整型 the k
* @return string字符串vector<vector<>>
*/
typedef pair<int,string > PIS;
vector<vector<string> > topKstrings(vector<string>& strings, int k) {
// write code here
map<string,int> hash;
for(auto &c : strings) hash[c] ++ ;
vector<PIS> q;
for(auto [c,v] : hash) q.push_back({
v,c}); // <次数,元素>
int m = k;
k = q.size() - k + 1; // 快排里的k是从小到大的k
quick_sort(q,0,q.size() - 1,k);
vector<vector<string> > res(m);
for(int i = 0, j = q.size() - 1;i < m;i ++ ,j -- )
{
auto t = q[j];
res[i].push_back(t.second);
res[i].push_back(to_string(t.first));
}
return res;
}
bool cmp(PIS a,PIS b)
{
if(a.first != b.first) return a.first > b.first;
return a.second <= b.second;
}
void quick_sort(vector<PIS> &q,int l,int r,int k)
{
if(l >= r) return;
auto x = q[l + r >> 1].first;
//auto x = q[l + r >> 1];
int i = l - 1, j = r + 1;
while(i < j)
{
do i ++ ;while(q[i].first < x);
do j -- ;while(q[j].first > x);
// do i ++ ;while(!cmp(q[i],x));
// do j -- ;while(cmp(q[j],x));
if(i < j) swap(q[i],q[j]);
}
int cnt = j - l + 1;
if(cnt >= k) quick_sort(q, l, j, k);
else quick_sort(q, j + 1, r, k - cnt);
}
};
矩阵的最小路径和(DP)
class Solution {
public:
/**
*
* @param matrix int整型vector<vector<>> the matrix
* @return int整型
*/
int minPathSum(vector<vector<int> >& matrix) {
// write code here
int n = matrix.size(), m = matrix[0].size();
vector<vector<int>> f(n,vector<int>(m,1e9));
f[0][0] = matrix[0][0];
for(int i = 0;i < n;i ++)
for(int j = 0; j < m ;j ++ )
{
if(i == 0 && j == 0) continue;
if(i) f[i][j] = min(f[i][j],f[i-1][j] + matrix[i][j]);
if(j) f[i][j] = min(f[i][j],f[i][j - 1] + matrix[i][j]);
}
return f[n - 1][m - 1];
}
};
回文链表(双指针)
前置知识:1. 快慢指针找链表中点 2. 迭代翻转链表
时间O(n),空间O(1)
题解
/**
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
class Solution {
public:
/**
*
* @param head ListNode类 the head
* @return bool布尔型
*/
bool isPail(ListNode* head) {
// write code here
if(!head || !head->next) return true;
auto slow = head,fast = head->next;
while(fast->next != NULL && fast->next->next != NULL)
{
slow = slow->next;
fast = fast->next->next;
}
ListNode *right = reverse(slow->next);
ListNode *left = head;
slow->next = NULL;
while(left!=NULL && right !=NULL)
{
if(left->val != right->val) return false;
left = left->next;
right = right->next;
}
return true;
}
ListNode *reverse(ListNode *head)
{
auto a = head, b = head->next;
while(b != NULL)
{
auto c = b->next;
b->next = a;
a = b, b = c;
}
head->next = NULL;
return a;
}
};
根节点到叶子节点的节点值之和等于sum 的路径(递归)
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<vector<int>> res;
vector<int> path;
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
dfs(root,targetSum);
return res;
}
void dfs(TreeNode *root,int targetSum)
{
if(!root) return;
int v = root->val;
targetSum -= v;
path.push_back(v);
if(!root->left && !root->right)
{
if(targetSum == 0) res.push_back(path);
}
dfs(root->left,targetSum);
dfs(root->right,targetSum);
path.pop_back();
}
};
数组中出现次数超过一半的数字(投票算法)
时间O(n),空间O(1)
class Solution {
public:
int MoreThanHalfNum_Solution(vector<int> numbers) {
int cnt = 0, candidate;
for(auto c : numbers)
{
if(cnt == 0) candidate = c;
if(candidate == c) cnt ++;
else cnt --;
}
// 最后统计是否超过一半
cnt = 0;
for(auto c : numbers)
if(c == candidate) cnt ++;
if(cnt > numbers.size() / 2) return candidate;
return 0;
}
};
数组中未出现的最小正整数(交换法)
class Solution {
public:
/**
* return the min number
* @param arr int整型vector the array
* @return int整型
*/
int minNumberdisappered(vector<int>& arr) {
// write code here
// 交换法,把1放到arr[0] 的位置上,把数放到正确的位置上
// 时间O(n),空间O(1)
int n = arr.size();
for(int i = 0;i < n;i ++ )
while(arr[i] >= 1 && arr[i] <= n && arr[i] != arr[arr[i] - 1])
swap(arr[i],arr[arr[i] - 1]);
for(int i = 0;i < n;i ++ )
if(arr[i] != i + 1) return i + 1;
return n + 1;
}
};
链表内指定区间翻转(快慢指针)
前置知识:链表翻转,画图理解
/**
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
class Solution {
public:
/**
*
* @param head ListNode类
* @param m int整型
* @param n int整型
* @return ListNode类
*/
ListNode* reverseBetween(ListNode* head, int m, int n) {
// write code here
ListNode *dummy = new ListNode(-1);
dummy->next = head;
auto pre_p = dummy, p = head, q = dummy;
for(int i = 1;i < m;i ++ )
{
pre_p = pre_p->next;
p = p->next;
}
for(int i = 0;i < n;i ++ ) q = q->next;
auto q_next = q->next;
auto ptemp = p;
pre_p->next = reverse(p,n - m);
ptemp->next = q_next;
return dummy->next;
}
ListNode* reverse(ListNode *p,int n) // 翻转以p为头,区间为n,并返回翻转后的头结点
{
auto q = p->next;
for(int i = 0;i < n;i ++ )
{
auto next = q->next;
q->next = p;
p = q,q = next;
}
return p;
}
};
在两个长度相等的排序数组中寻找中位数(递归)
class Solution {
public:
/**
* find median in two sorted array
* @param arr1 int整型vector the array1
* @param arr2 int整型vector the array2
* @return int整型
*/
int findMedianinTwoSortedAray(vector<int>& nums1, vector<int>& nums2) {
// write code hereint tot = nums1.size() + nums2.size();
int tot = nums1.size() + nums2.size();
if(tot % 2 == 0)
{
return find(nums1,0,nums2,0,tot / 2);
}
else return find(nums1,0,nums2,0,tot / 2 + 1);
}
int find(vector<int>& nums1,int i ,vector<int> &nums2,int j,int k)
{
if(nums1.size() - i > nums2.size() - j) return find(nums2,j,nums1,i,k);
if(nums1.size() == i) return nums2[j + k - 1];
if(k == 1) return min(nums1[i],nums2[j]);
int si = min(i + k / 2, (int)nums1.size()), sj = j + k - k / 2;
if(nums1[si - 1] > nums2[sj - 1])
return find(nums1,i,nums2,sj,k - (sj - j));
else
return find(nums1,si,nums2,j,k - (si - i));
}
};
二叉树根节点到叶子节点所有路径之和(递归)
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
int sumNumbers(TreeNode* root) {
return dfs(root,0);
}
int dfs(TreeNode *root,int sum)
{
if(!root) return 0;
int res = sum * 10 + root->val; // 计算本层
// 计算到叶结点
if(!root->left && !root->right)
return res;
return dfs(root->left,res) + dfs(root->right,res); // 交给下层继续计算
}
};
判断二叉树是否对称(递归,栈)
递归
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
bool isSymmetric(TreeNode* root) {
if(!root) return true;
return dfs(root->left,root->right);
}
bool dfs(TreeNode *p, TreeNode *q)
{
// if(p == NULL && q != NULL) return false;
// if(p != NULL && q == NULL) return false;
// if(p == NULL && q == NULL) return true;
if(!p || !q) return !p && !q;
return p->val == q->val && dfs(p->left,q->right) && dfs(p->right,q->left);
}
};
迭代
/**
* 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:
bool isSymmetric(TreeNode* root) {
// 递归改迭代,用栈模拟
if(!root) return true;
stack<TreeNode*> left,right;
auto l = root->left, r = root->right;
while(l || r || left.size() || right.size())
{
while(l && r)
{
left.push(l),l = l->left;
right.push(r),r = r->right;
}
if(l || r) return false;
l = left.top(),left.pop();
r = right.top(), right.pop();
if(l->val != r->val) return false;
l = l->right, r = r->left;
}
return true;
}
};