首页 > 其他分享 >顺序表应用题

顺序表应用题

时间:2022-08-20 18:46:04浏览次数:84  
标签:顺序 nums int 应用题 vector 元素 nums1 nums2

1. 删除返回最小值并由最后元素填补

bool Del_Min(vector<int>& nums,int &val) {
    if(nums.size()==0) return false;
    int pos = 0;//假定0号元素最小
    for(int i=1;i<nums.size();i++)
        if(nums[i]<nums[pos])
            pos = i;//找最小值下标
    val = nums[pos];//返回最小值
    nums[pos] = nums.back();//替换删除值
    nums.pop_back();//长度减一
    return true;
}

2. 逆置所有元素

void Reverse(vector<int>& nums) {
    int n = nums.size();
    for(int i=0;i<nums.size()/2;i++)
        swap(nums[i],nums[n-1-i]);
}

3. 删除所有指定值

void del_x(vector<int>& nums,int val) {
    //本质上是重新更改映射
    int k =0;//记录不等于val的个数
    for(int i=0;i<nums.size();i++)
        if(nums[i]!=val)
            nums[k++] = nums[i];
    //修改数组长度为k
}

4. 有序表中删除所有指定范围值

//与题3解法相同,由于是有序表,也可以先找映射前后的下标,再一一映射
bool Del_s_t(vector<int>& nums,int s,int t) {
    int i , j;
    if(s>=t||nums.size()==0) return false;
    for(i=0;i<nums.size()&&nums[i]<s;i++);//找映射左下标,第一个大于等于s的值
    for(j=i;j<nums.size()&&nums[j]<=t;j++);//找映射右下标,第一个大于t的值
    for(;j<nums.size();j++)
        nums[i] = nums[j];//重新映射
    //修改数组长度为i
    return true;

5. 删除所有指定范围值

void Del_s_t(vector<int>& nums,int s,int t) {
    //本质上是重新更改映射
    int k =0;//记录不在目标范围的个数
    for(int i=0;i<nums.size();i++)
        if(nums[i]<s||nums[i]>t)
            nums[k++] = nums[i];
    //修改数组长度为k
}

6. 有序表中删除重复值

bool Del_same(vector<int>& nums) {
    if(nums.size()==0) return false;
    int i , j;//双指针映射
    for(i=0,j=1;j<nums.size();j++)
        if(nums[i]!=nums[j])
            nums[++i] = nums[j];//拓展映射数组
    //修改数组长度为i+1
    return true;
}

7. 有序顺序表合并

vector<int> merge(vector<int>& v1,vector<int>& v2) {
    vector<int> res(v1.size()+v2.size());
    int i = 0,j=0,k=0;
    while(i<v1.size()&&j<v2.size()){
        if(v1[i]<v2[j]) res[k++] = v1[i++];
        else res[k++] = v2[j++];
    }
    while(i<v1.size()) res[k++] = v1[i++];
    while(i<v1.size()) res[k++] = v2[j++];
    return res;
}

8. 两区域元素位置互换(原地)

//先全部逆置,再分区域逆置
void Exchange(vector<int>nums,int m,int n){
    Reverse(nums,0,m+n-1);
    Reverse(nums,0,n-1);
    Reverse(nums,n,m+n-1);
}

void Reverse(vector<int>& nums,int left,int right) {
    for(int i=left;i<(left+right)/2;i++)
        swap(nums[i],nums[right-i]);
}

9. 二分查找并插入

void bisearch(vector<int> nums,int val.int n){
    int low = 0,high = n-1;
    int mid;
    while(low<=high){//循环结束后,若没找到,high小于val,low大于val
        mid = (low + high)/2;
        if(nums[mid]==val) break;//找到目标值
        else if(nums[mid]<val) low = mid + 1;
        else high = mid -1;
    }
    if(nums[mid]==val&&mid!=n-1)
        swap(nums[mid],nums[mid+1]);//题目要求
    if(low>high){
        for(i=n-1;i>high;i--) nums[i+1] = nums[i];//后移元素,空出high后面元素
        nums[high+1] = val;//插入值
    }
}

10. 循环左移p个位置

//最优解类似题8,实质上等价于将p个元素区域和n-p个元素区域互换
三个逆置时间复杂度分别为O(p/2),O((n-p)/2),O(n/2)
故时间复杂度为O(n),空间复杂度为O(1)
//解法2借用一个辅助单元实现右移1位的操作,循环p次
//解法3借用p个辅助单元来进行移动

11. 求两升序序列中位数

//由于题目是等长序列,可以简单递归使问题规模不断变小
int medium(vector<int>& nums1, vector<int>& nums2, int s1, int d1, int s2, int d2) {
    //之所以偶数递归加一,是因为整除向下取整
    int m1 = (s1 + d1) / 2;
    int m2 = (s2 + d2) / 2;
    if (s1 == d1 && s2 == d2) return nums1[s1] < nums2[s2] ?  nums1[s1] : nums2[s2];//边界条件
    if (nums1[m1] == nums2[m2]) return nums1[m1];
    if (nums1[m1] < nums2[m2]) {
        if ((s1 + d1) % 2 == 0)//若元素个数为奇数
            return medium(nums1, nums2, m1, d1, s2, m2);//舍弃nums1前面元素和nums2后面元素
        else //若元素个数为偶数
            return medium(nums1, nums2, m1 + 1, d1, s2, m2);//舍弃并保证双方还是偶数
    }
    else {
        if ((s2 + d2) % 2 == 0)//若元素个数为奇数
            return medium(nums1, nums2, s1, m1, m2, d2);//舍弃nums1后面元素和nums2前面元素
        else //若元素个数为偶数
            return medium(nums1, nums2, s1, m1, m2 + 1, d2);//舍弃并保证双方还是偶数         
    }
}

标签:顺序,nums,int,应用题,vector,元素,nums1,nums2
From: https://www.cnblogs.com/929code/p/16608382.html

相关文章