topk
class Solution {
public:
int partition(vector<int>& nums,int i,int j)
{
int pviot = nums[i];
while(i < j)
{
for(;i<j && nums[j] <= pviot ;--j);
nums[i] = nums[j];
for(;i<j && nums[i] >= pviot;++i);
nums[j] = nums[i];
}
nums[i] = pviot;
return i;
}
int quickSort(vector<int>& nums,int i,int j ,int k)
{
int pos = partition(nums,i,j);
if(k > pos)
return quickSort(nums,pos+1,j,k);
else if( k < pos)
return quickSort(nums,i,pos-1,k);
else
return nums[pos];
}
int findKthLargest(vector<int>& nums, int k) {
return quickSort(nums,0,nums.size()-1,k-1);
}
};
手撕堆排
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
* 将给定数组排序
* @param arr int整型vector 待排序的数组
* @return int整型vector
*/
void HeapShiftDown(vector<int>& arr,int k,int n)
{
for(int m = k*2+1; m < n; m=m*2+1)
{
if(m+1 < n && arr[m+1] > arr[m])
m++;
if(arr[m]> arr[k])
{
swap(arr[k],arr[m]);
k = m;
}
else
break;
}
}
void HeapAdjust(vector<int>& arr)
{
int k = (arr.size()-1)/2;
for(int i = k; i >=0;--i)
HeapShiftDown(arr,i,arr.size());
}
vector<int> MySort(vector<int>& arr) {
// write code here
int n = arr.size();
HeapAdjust(arr);
for(int i = n-1;i>0;--i)
{
swap(arr[0],arr[i]);
HeapShiftDown(arr,0,i);
}
return arr;
}
};
手撕快速
-
class Solution { public: /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * 将给定数组排序 * @param arr int整型vector 待排序的数组 * @return int整型vector */ int Partition(vector<int>& nums,int i,int j) { int pivot = nums[i]; while(i<j) { while(i<j && nums[j] >= pivot) --j; nums[i] = nums[j]; while(i<j && nums[i] <= pivot) ++i; nums[j] = nums[i]; } nums[i] = pivot; return i; } void QuickSort(vector<int>& nums,int i,int j) { if(i < j) { int index = Partition(nums,i,j); QuickSort(nums, i, index-1); QuickSort(nums, index+1, j); } } vector<int> MySort(vector<int>& arr) { // write code here QuickSort(arr, 0, arr.size()-1); return arr; } };
手撕归并
#include <iostream>
#include <vector>
using namespace std;
void Merge(vector<int>& nums,int i,int mid,int j)
{
vector<int> v;
int a=i,b=mid+1;
while(a <= mid && b <=j)
{
if(nums[a] < nums[b])
{
v.push_back(nums[a]);
++a;
}
else
{
v.push_back(nums[b]);
++b;
}
}
while(a <= mid)
{
v.push_back(nums[a]);
++a;
}
while(b <= j)
{
v.push_back(nums[b]);
++b;
}
for(int k= 0; k< v.size();++k)
nums[i+k] = v[k];
}
void MergeSort(vector<int>& nums,int i,int j)
{
if(i < j)
{
int mid = i + (j-i)/2;
MergeSort(nums,i,mid);
MergeSort(nums,mid+1,j);
Merge(nums,i,mid,j);
}
}
int main()
{
int n;
cin>>n;
vector<int> v(n,0);
for(int i = 0; i< n; ++i)
{
cin>>v[i];
}
MergeSort(v,0,n-1);
for(int i =0; i < v.size();++i)
{
cout<<v[i];
if(i != v.size()-1)
cout<<" ";
}
return 0;
}
最长回文字串
- dp
class Solution {
public:
string longestPalindrome(string s) {
string res;
vector<vector<bool>> dp(s.size(),vector<bool>(s.size(),false));
for(int i = s.size()-1; i>=0 ;--i)
{
for(int j = i; j < s.size();++j)
{
if( (j-i > 1 && s[i] == s[j] && dp[i+1][j-1]) || (j-i <= 1 && s[i] == s[j] ))
{
dp[i][j] = true;
if(j-i+1 > res.size())
res = s.substr(i,j-i+1);
}
}
}
return res;
}
};
中心扩展
class Solution { public: pair<int,int> expandAroundCenter(string s,int i,int j) { while(i>=0 && j < s.size() && s[i] == s[j]) { --i; ++j; } return {i+1,j-1}; } string longestPalindrome(string s) { int start=0,end = 0; for(int i = 0; i < s.size();++i) { auto [left1,right1] = expandAroundCenter(s,i,i); auto [left2,right2] = expandAroundCenter(s,i,i+1); if(right1 -left1 > end -start) { end = right1; start = left1; } if(right2 - left2 > end - start) { end = right2; start = left2; } } return s.substr(start,end-start+1); } };
最大连续子数组的和
- dp
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int n = nums.size();
int res = nums[0];
vector<int> dp(n,nums.size());
dp[0] = nums[0];
for(int i = 1; i < nums.size();++i)
{
if(dp[i-1] + nums[i] < nums[i])
dp[i] = nums[i];
else
dp[i] = dp[i-1] + nums[i];
res = max(res,dp[i]);
}
return res;
}
};
如果删除vector中间元素 怎么实现(不能用erease,无序)
- 将中间之后的元素往前移动一个位置并vector大小减一
strcpy
#include <QCoreApplication>
#include <assert.h>
#include <QDebug>
//普通版本的strcpy,实现没有检查dst和src内存重叠问题,会崩溃
char* myStrcpy(char* dst, const char* src)
{ //const约束,内容不可变
assert(src != Q_NULLPTR && dst != Q_NULLPTR); //参数非0检验
char* pstr = dst;
while ((*dst++ = *src++) != '\0'){}
return pstr;
}
//检查内存重叠
char* my1Strcpy(char* dst, const char* src)
{
assert(src != Q_NULLPTR && dst != NULL);
char * nsrc = const_cast<char*>(src);
char * adest = dst;
size_t size = strlen(src);
if (src < dst && (src + size) > dst) {
//内存重叠,从后向前复制
char* bsrcp = nsrc + size - 1;
char* bdestp = dst + size - 1;
while ((*bdestp-- = *bsrcp--) && size-- != 0){}
} else {
while ((*dst++ = *nsrc++) != '\0'){}
}
return dst;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
char dest[10] = "hello";
qDebug() << my1Strcpy(&dest[3], dest) << endl;
return a.exec();
}
输入1~n共n个数,打乱后随机删除一个,找出删除的那个数(不许排序)
对于删除一个数,大概有四种方法:
(1)用1+2+…+n减去当前输入数据的总和。时间复杂度:O(n) 空间复杂度:O(1) 【容易溢出】
(2)用12…n除以当前输入数据的总积。时间复杂度:O(n) 空间复杂度:O(1) 【容易溢出】
(3)用1^2^…^n的结果在逐个异或当前输入数据。时间复杂度:O(n) 空间复杂度:O(1)
(4)对输入数据进行Hash,然后从头到尾遍历一次。时间复杂度O(n) 空间复杂度O(n)
输入1~n共n个数,打乱后随机删除一个,再复制一个,找出这两个数
类似 剑指 Offer 56 - I. 数组中数字出现的次数
- 第一轮整体遍历,求出a^b(因为相同的数字异或为0,0异或任何数字为数字自身)
- 然后结合a^b以及原来数组求出这两个数字
- 原理:用一个只有一位为1的数字来遍历异或整个数组,把这个数组分成两个子数组(异或结果相同的数字在同一个子数组),如果是两个相同的数字,它们一定在同一个子数组里(保证子数组异或时为0),现在只需要把两个只出现一次的数字分到不同的子数组,那么子数组分别遍历异或得到的两个数字就是这两个数字。
- 怎么把两个只出现一次的数字分到不同地子数组?
- 找到a^b第一个为1的位置,异或结果为1说明a和b在这一位上不同,那用只有这一位为1的数字m去分别异或a和b,得到的结果一定不同,也就把a和b分到了不同的子数组。结合上一点得出结果。
实在写不出来hash
非递归遍历
/**
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
class Solution {
public:
/**
*
* @param root TreeNode类 the root of binary tree
* @return int整型vector<vector<>>
*/
vector<int> preorder(TreeNode* root)
{
vector<int> res;
stack<TreeNode*> s;
TreeNode* cur;
s.push(root);
while(!s.empty())
{
cur = s.top();
s.pop();
res.push_back(cur->val);
if(cur->right)
s.push(cur->right);
if(cur->left)
s.push(cur->left);
}
return res;
}
vector<int> inorder(TreeNode* root)
{
vector<int> res;
stack<TreeNode*> s;
TreeNode* cur = root;
while(!s.empty() || cur != nullptr)
{
if(cur != nullptr)
{
s.push(cur);
cur = cur->left;
}
else
{
cur = s.top();
s.pop();
res.push_back(cur->val);
cur = cur->right;
}
}
return res;
}
vector<int> postoreder(TreeNode* root)
{
vector<int> res;
stack<TreeNode*> s;
TreeNode* cur = root;
TreeNode* pre = nullptr;
while(!s.empty() || cur != nullptr)
{
if(cur!=nullptr) {
s.push(cur);
cur = cur->left;
}
else {
cur = s.top();
s.pop();
if(cur->right==nullptr || pre==cur->right) { // 访问节点的条件
res.push_back(cur->val); // 访问
pre = cur; // 这一步是记录上一次访问的节点
cur = nullptr; // 此处为了跳过下一次循环的访问左子节点的过程,直接进入栈的弹出阶段,因为但凡在栈中的节点,它们的左子节点都肯定被经过且已放入栈中。
}
else
{ // 不访问节点的条件
s.push(cur); // 将已弹出的根节点放回栈中
cur = cur->right; // 经过右子节点
}
}
}
return res;
}
vector<vector<int> > threeOrders(TreeNode* root) {
// write code here
vector<vector<int> > res;
res.push_back(preorder(root));
res.push_back(inorder(root));
res.push_back(postoreder(root));
return res;
}
};