2022-04-10算法题TopK_排序_atoi_两数组中位数

本文详细介绍了多种排序算法,包括冒泡排序、快速排序、归并排序和计数排序,并提供了具体的实现代码。此外,还探讨了如何解决TopK问题,以及如何寻找数组中的第k大元素。同时,文章提及了字符串转换整数、查找两个数的中位数以及求解线性回归模型等算法。
摘要由CSDN通过智能技术生成

TopK问题及其延申

912. 排序数组

冒泡

class Solution {
public:
    vector<int> sortArray(vector<int>& nums) {
        int n=nums.size();
        for(int i=0;i<n-1;++i){//冒泡n-1次
            for(int j=1;j<n-i;++j){//每次确定最后一位,内层循环少一个
                if(nums[j]<nums[j-1]){
                    swap(nums[j],nums[j-1]);
                }
            }
        }
        return nums;
    }
};

快排
参考题解

class Solution {
public:
    void QuickSort(vector<int>& arr, int start, int end){
        if(start >= end) return;
        int index=rand()%(end-start+1)+start;
        int pivot=arr[index];
        swap(arr[start], arr[index]);
        int i=start, j=end;
        while(i<j){
            while(i<j && arr[j]>=pivot)
                j--;
            while(i<j && arr[i]<=pivot)
                i++;
            if(i!=j){
                swap(arr[i], arr[j]);
            }
        }
        swap(arr[start], arr[i]);
        //最后是i==j了,因为先动的j,所以arr[j]可能<pivot,但arr[i]不可能>pivot
        QuickSort(arr,start,i-1);
        QuickSort(arr,i+1,end);
        return;
    }
    vector<int> sortArray(vector<int>& nums) {
        QuickSort(nums, 0, nums.size()-1);
        return nums;
    }
};

归并
参考题解

class Solution {
public:
    void merge(vector<int> &nums, int left, int right, vector<int> &ans){
        int mid=(left+right)/2;
        int i=left, j=mid+1;
        int k=0;
        while(i<=mid && j<=right){
            if(nums[i]<nums[j]){
                ans[k++]=nums[i++];
            }
            else{
                ans[k++]=nums[j++];
            }
        }
        while(i<=mid){
            ans[k++]=nums[i++];
        }
        while(j<=right){
            ans[k++]=nums[j++];
        }
        for(int p=left;p<=right;++p){
            nums[p]=ans[p-left];
        }
        return;
    }
    void MergeSort(vector<int> &nums, int left, int right, vector<int> &ans){
        if(left>=right) return;
        int mid=(left+right)/2;
        MergeSort(nums, left, mid, ans);
        MergeSort(nums, mid+1, right, ans);
        merge(nums, left, right, ans);//合并左右两半已排序数组
        //return;
    }
    vector<int> sortArray(vector<int>& nums) {
        vector<int> ans(nums.size());
        MergeSort(nums, 0, nums.size()-1, ans);
        return nums;
    }
};

计数排序

class Solution {
public:
    vector<int> sortArray(vector<int>& nums) {
        int n=nums.size();
        int minnum=nums[0],maxnum=nums[0];
        for(int i=1;i<n;++i){
            if(nums[i]<minnum) minnum=nums[i];
            if(nums[i]>maxnum) maxnum=nums[i];
        }
        vector<int> v(maxnum-minnum+1,0);//maxnum-minnum+1的空间复杂度
        for(int i=0;i<n;++i){
            v[nums[i]-minnum]++;//对minnum+v中序号计数
        }
        int start=0;
        for(int i=0;i<v.size();++i){
            while(v[i]>0){
                nums[start]=i+minnum;
                start++;
                v[i]--;
            }
        }
        return nums;
    }
};

215. Top K

部分快排,沿用上面的快排模板,partition返回本轮确定位置的数的下标,如果等于n-k(第k大下标是从小到大序列的n-k),就返回,<n-k,在右边找,>n-k,左边找

topk 的小错:

	int index=rand()%(right-left+1)+left; 

注意right-left+1

    int left=0, right=n-1;
    int index=partition(nums, left, right);

注意left,right先声明了,不然下面更新left,right 可能出问题

class Solution {
public:
    int partition(vector<int> &nums, int left, int right){
        int index=rand()%(right-left+1)+left;
        int pivot=nums[index];
        swap(nums[index], nums[left]);
        int i=left, j=right;
        while(i<j){
            while(i<j && nums[j]>=pivot) j--;
            while(i<j && nums[i]<=pivot) i++;
            if(i!=j){
                swap(nums[i], nums[j]);
            }
        }
        swap(nums[left], nums[i]);
        return i;
    }
    int findKthLargest(vector<int>& nums, int k) {
        //第k大,下标是n-k,第1大是n-1,类推
        int n=nums.size();
        k=n-k;
        int left=0, right=n-1;
        int index=partition(nums, left, right);
        while(index!=k){
            if(index<k){
                left=index+1;
            }
            else right=index-1;
            index=partition(nums, left, right);
        }
        return nums[index];
    }
};

手写大根堆
参考题解

有没有更快的方法
计数排序,但是空间复杂度高

桶排序:大数据或者内存不足的情况使用,O(N)找到最大最小数,差值t,分根号t个桶子,小于最小数+根号t的放在第一个桶子里,以此类推,O(n)+O(n^(1/2)*log( n^(1/2 ))

链表排序

8. 字符串转换整数 (atoi)

自己写的版本,用long,maxvalue是最大,minvalue是最小的绝对值。

class Solution {
public:
    int myAtoi(string s) {
            int k=0;
            int n=s.size();
            long ans=0;
            long maxvalue=pow(2,31)-1;
            long minvalue=pow(2,31);
            if(n==0) return 0;
            while(k<n){
                    if(s[k]==' ') k++;
                    else break;
            }
            bool neg=0;
            if(s[k]=='+') k++;
            else if(s[k]=='-'){
                    neg=1;
                    k++;
            }
            while(k<n){
                    if(!isdigit(s[k])) break;
                    else{
                            if(!neg && (ans==maxvalue/10 )&& ((int(s[k]-'0')>=maxvalue%10))){
                                    ans=maxvalue;
                                    return ans;
                            }
                            else if(neg &&( ans==minvalue/10) && ((int(s[k]-'0')>=minvalue%10))){
                                    ans=0-minvalue;
                                    return ans;
                            }
                            else if(!neg && (ans>maxvalue/10 )){ return maxvalue;}
                            else if(neg && ( ans>minvalue/10)) return -1*minvalue;
                            ans=ans*10+(int(s[k]-'0'));
                            k++;
                    }
            }
            if(neg) return -1*ans;
            else return ans;
    }
};

优化边界处理,这里可以不用long,maxalue设置成MAX_INT/10就可

class Solution {
public:
    int myAtoi(string s) {
            int k=0;
            int n=s.size();
            long ans=0;
            long maxvalue=pow(2,31)-1;
            long minvalue=pow(2,31);
            if(n==0) return 0;
            while(k<n){
                    if(s[k]==' ') k++;
                    else break;
            }
            bool neg=0;
            if(s[k]=='+') k++;
            else if(s[k]=='-'){
                    neg=1;
                    k++;
            }
            while(k<n){
                    if(!isdigit(s[k])) break;
                    else{
                            int num=int(s[k]-'0');
                            if(ans>maxvalue/10){
                                    if(neg) return -minvalue;
                                    else return maxvalue;
                            }
                            else if(ans==maxvalue/10){
                                    if(!neg && num>=maxvalue%10) return maxvalue;
                                    else if(neg && num>=minvalue%10) return -minvalue; 
                            }
                            ans=ans*10+num;
                            k++;
                    }
            }
            if(neg) return -ans;
            else return ans;
    }
};

查找两个数的中位数(一步步深入,先从空间复杂度O(n+m)到时间负责度O(n+m)到O(log(n+m))

层序遍历

非递归中序遍历 栈->Morriss

336. 回文对

暴力解法(超时)

class Solution {
public:
    bool ishuiwen(string str){
        int n=str.size();
        if(n<=1) return true;
        int start=0,end=n-1;
        while(start<end){
            if(str[start]==str[end]){
                start++;
                end--;
            }
            else return false;
        }
        return true;
    }
    vector<vector<int>> palindromePairs(vector<string>& words) {
        int n=words.size();
        vector<vector<int>> v;
        for(int i=0;i<n;++i){
            for(int j=0;j<n; ++j){
                if(j==i) continue;
                string str=words[i]+words[j];
                if(ishuiwen(str)){
                    v.push_back({i,j});
                }
            }
        }
        return v;
    }
};

哈希表解法
看起来就这个比较好写,适合面试手撕,故取这个。
官方题解

其他解法:
字典树
字典树+马拉车

504. 七进制数

除留余数法

class Solution {
public:
    string convertToBase7(int num) {
            if(num==0) return "0";
            bool neg=num>0;
            string s="";
            num=abs(num);
            while(num>0){
                    s.push_back('0'+num%7);
                    num/=7;
            }
            if(!neg) s.push_back('-');
            reverse(s.begin(), s.end());
            return s;
    }
};

1143. 最长公共子序列

O(m*n)

class Solution {
public:
    int longestCommonSubsequence(string text1, string text2) {
            int m=text1.size(), n=text2.size();
            vector<vector<int>> dp(m+1, vector<int>(n+1,0));
            int ans=0;
            for(int i=1;i<=m;++i){
                    for(int j=1; j<=n; ++j){
                            if(text1[i-1]==text2[j-1]){
                                    //i 和j是dp的下标,增加一行0和一列0,从1到n
                                dp[i][j]=dp[i-1][j-1]+1;
                                ans=max(ans, dp[i][j]);
                            }
                            else{
                                dp[i][j]=max(dp[i-1][j], dp[i][j-1]);
                                ans=max(ans, dp[i][j]);
                            }
                    }
            }
            return ans;
    }
};

300. 最长递增子序列

参考题解

//O(nlogn)
class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
            vector<int> tails(nums.size(),0);
            int res=0;
            for(auto num:nums){
                    int i=0, j=res;
                    while(i<j){
                            int m=(i+j)/2;
                            if(num>tails[m]) i=m+1;
                            else j=m;
                    }
                    tails[i]=num;
                    if(j==res) res++;
            }
            return res;
    }
};
// O(n^2)
class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
            int ans=1;
            int n=nums.size();
            vector<int> dp(n,1);
            for(int i=0; i<n;++i){
                    for(int j=0; j<i;++j){
                            if(nums[i]<=nums[j]){
                                    continue;
                            }
                            else{
                                    dp[i]=max(dp[i], dp[j]+1);
                            }
                    }
            }
            for(auto k:dp){
                    ans=max(ans,k);
            }
            return ans;
    }
};

二分法解方程

以算根号2为例

double d=2;
double eps = 0.000001;

double f(double x) {
    return x * x;
}
int main() {
    double l = 0, r = d;
    double mid = (l + r) / 2;
    while (abs(f(mid)-d) >= eps) {
        mid = (l + r) / 2;
        if (f(mid) - d < 0) {
            l = mid;
        }
        else r = mid;
    }
    cout << setprecision(7) << mid << endl;
    return 0;
}

x^3+4*x-10=0在(1,2)的近似解

double d=0;
double eps = 0.000001;
double f(double x) {
    //return x * x;
    return pow(x, 3) + 4 * x - 10;
}
int main() {
    double l = 1, r = 2;
    double mid = (l + r) / 2;
    while (abs(f(mid)-d) >= eps) {
        mid = (l + r) / 2;
        if (f(mid) - d < 0) {
            l = mid;
        }
        else r = mid;
    }
    cout << setprecision(7) << mid << endl;
    return 0;
}

tf-idf

tf-idf

手写线性回归模型

手撕线性回归

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值