为编程爱好者分享易语言教程源码的资源网
好用的代理IP,游戏必备 ____广告位招租____ 服务器99/年 ____广告位招租____ ____广告位招租____ 挂机,建站服务器
好用的代理IP,游戏必备 ____广告位招租____ 服务器低至38/年 ____广告位招租____ ____广告位招租____ 挂机,建站服务器

网站首页 > 网络编程 > 其它综合 正文

题海战术——线性枚举

三叶资源网 2022-11-21 19:18:50 其它综合 153 ℃ 0 评论

编写一个函数,将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。

必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。

思路分析:

翻转其实就是相当于第一个字符和最后一个交换

首先实现一个交换函数,依次枚举

引用传递:被调函数的形式参数虽然也作为局部变量在堆栈中开辟了内存空间,但是这时存放的是主调函数

放进来的实参变量地址.被调函数对形参的任何操作都被处理成间接寻址.就是通过对阵中存放的地址访问主调函数中

的实参变量.


/*
简单的说,就是在函数调用的参数,可以传引用,从而使得函数返回时,传参值的改变依旧生效
*/
class Solution {
public:
	void swap(char& a, char& b) {//引用传递
    
		char tmp = a;
		a = b;
		b = tmp;
	}
	void reverseString(vector<char>&)s){
	int len = s.size();
	for (int i = 0; i < len / 2; i++) {//注意枚举范围
		swap(s[i], s[len - i - 1]) 
		
	}
}
};

??给定一个字符串,需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序。

思路分析:

记录一个pre变量,初始化为0,然后开始枚举整个字符串,只要遇到空格或字符串结尾.就令当前枚举的位置为i,我们就将[pre,i-1]的字符逆序放入字符串中.再加一个空格.枚举完毕,将结果字符串返回即可

/*
两个for循环嵌套枚举时,算法时间复杂度不一定是n的平方.也不一定是乘法关系.也有可能的加法关系
*/

class Solution {
public:
    string reverseWords(string s) {  //传参是string,返回值也是string  支持动态扩容
      
        string ans = "";                             // (1)初始化结果字符串ans为空字符串
        int pre = 0;                                 // (2)初始化pre变量为0,代表字符串下标0开始
        for(int i = 0; i <= s.length(); ++i) {       // (3)注意这里需要枚举到s.length(),以空格分隔的字符串
          //最后部分会漏掉
            if(i == s.length() || s[i] == ' ') {     // (4)遇到字符串结尾或者空格,就开始处理pre到i-1的部分
                for(int j = i-1; j >= pre; --j) {    
                    ans.push_back(s[j]);             // (5)对这部分字符.逆序放进结果数组,采用push_back接口
                }
                if(i < s.length())                   // (6)如果不是字符串结尾.则补上一个空格
                    ans.push_back(' ');
                pre = i + 1;                         // (7)更新pre的位置为空格下一个字符的下标
            }
        }
        return ans;
    }
};

给出一个有序数组 nums ,请 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。不要使用额外的数组空间。

传参是一个vector<int>类型的引用,要求在这个数组基础上进行修改

思路分析;

由于数组是有序的.所以大小相等的数一定出现在连续的一段区间.所以.核心是比较,如果

相等则舍弃,不相等就放入候选数组.由于我们做的是删除操作,所以候选数组的长度

在任何时候一定小于原数组,所以候选数组可以和原数组是同一块内存空间

class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        int nowIdx = 0;                          // (1)nowIdx记录的是有序不重复数组最后一个元素的下标
        if(nums.size() == 0) {
            return 0;
        }
        for(int i = 1; i < nums.size(); ++i) {   // (2)从第一个元素开始枚举.将当前元素和有序
          //不重复数组最后一个元素进行比较.如果不相等.则将当前元素放到有序不重复数组最后
          //一个元素.更新下标
            if(nums[i] != nums[nowIdx]) {
                nums[++nowIdx] = nums[i];
            }
        }
        return nowIdx + 1;                       // (3)由于数组下标从0 开始.所以返回长度需要+1
    }
};

给你一个整数数组nums,请你选择数组的两个不同下标 i 和 j ,使 (nums[i]-1)*(nums[j]-1)取得最大值。请你计算并返回该式的最大值。

思路分析;

由于所有数都是整数,其实这个问题就是找到有个数列中的前两个大的数即可

线性枚举,往往就是对数组进行操作.而且是进行遍历操作

int maxProduct(int* nums, int numsSize){
    int i;
    int max = -1, nextmax = -1;       // (1) 初始化最大值和次大值
    for(i = 0; i < numsSize; ++i) {
        if(nums[i] > max) {           // (2) 枚举到的当前数和最大值换大,则更新次大值
          //和最大值
            nextmax = max;
            max = nums[i];
        }else if(nums[i] > nextmax) { // (3) 枚举到的当前数在次大值和最大值之间,则更新次大值
            nextmax = nums[i];
        }
    }
    return (max-1) * (nextmax-1);
}

给定一个二进制数组, 计算其中最大连续 1 的个数。

思路分析:

连续就是当前这个数和前一个数的关系,二进制数组不是0就是1.当前数为0,sum=0

当前数为1时,++sum;然后统计这个过程中sum最大值

int findMaxConsecutiveOnes(int* nums, int numsSize){
    int i;
    int sum = 0, max = 0;
    for(i = 0; i < numsSize; ++i) {
        if(nums[i] == 0) {
            sum = 0;                 // (1)当前数字为0,
        }else {
            ++sum;                   // (2)当前数字为1,则sum=sum+1
            if(sum > max) {
                max = sum;           // (3)随时记录最大值
            }
        }
    }
    return max;
}

寻找数组中的最小值并返回

思路分析;

这个很简单,不要想太多.直接遍历一遍,比较小的数存在临时变量上,最后这个临时变量就是最小值

int findMin(int* nums, int numsSize){
    int i, min = 100000;
    for(i = 0; i < numsSize; ++i) {
        if(nums[i] < min) {             // (1)如果当前枚举的数比最小值小,直接赋值给最小值
            min = nums[i];
        }
    }
    return min;
}

给定一个由 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一。
??最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。
??你可以假设除了整数 0 之外,这个整数不会以零开头。

思路分析:

考虑全是9的情况,数组长度需要+1,其他情况直接顺位模拟加法和进位即可

利用数组可以对大整数进行进位模拟加法

int* plusOne(int* digits, int digitsSize, int* returnSize){
    int i, add;
    int *ret = NULL;
    for(i = 0; i < digitsSize; ++i) {
        if(digits[i] != 9) {
            break;
        }
    }
    if(i == digitsSize) {                                       // (1)处理99999+1
        ret = (int *) malloc( (digitsSize + 1) * sizeof(int));
        ret[0] = 1;
        for(i = 1; i < digitsSize + 1; ++i) {
            ret[i] = 0;
        }
        *returnSize = digitsSize + 1;
        return ret;
    }
                                                                // (2)处理其他情况
    ret = (int *) malloc( digitsSize * sizeof(int));
    *returnSize = digitsSize;
    add = 1;                                                    // (3)add代表上一个位的进位,由于是+1,默认最低位进位是1
    for(i = digitsSize - 1; i >= 0; --i) {
        ret[i] = digits[i] + add;
        if(ret[i] >= 10) {                                      // (4)如果大于等于10,产生进位
            ret[i] -= 10;
            add = 1;
        }else {
            add = 0;                                            // (5)不产生进位
        }
    }
    return ret;
}

输入数字 n ,按顺序打印出从 1 到最大的 n 位十进制数。比如输入 3,则打印出 1、2、3 一直到最大的 3 位数 999。

思路分析:

通过遍历,不段乘10,乘了n次.得到的就是10的n次方,10的n次方-1就是n位数的最大值

剩下的就是从1开始遍历到这个最大值的过程了

int* printNumbers(int n, int* returnSize){
    int i;
    int f = 1;
    int *ret;

    for(i = 0; i < n; ++i) {
        f *= 10;                               // (1)计算10的n次方
    }
    --f;
    *returnSize = f;
    ret = (int *)malloc( f * sizeof(int) );
    for(i = 1; i <= f; ++i) {
        ret[i-1] = i;                          // (2)遍历,存储在数组中
    }
    return ret;
}

给定一个整型数组 nums,在数组中找出由三个数组成的最大乘积,并输出这个乘积

思路分析:

线性枚举要先排序,接下来处理问题会很方便

三个负数: 排序后,找最接近零的三个数

两个负数:最大的正数,最小的负数

一个负数:最小的两个正数,最接近零的负数

没有负数:最大的三个正数


int threeNegative(int* nums, int numsSize) {
    int i;
    for(i = 0; i < numsSize; ++i) {
        if(nums[i] >= 0) {
            break;
        }
    }
    if(i - 3 < 0) {
        return -1000000009;
    }
    return nums[i-1] * nums[i-2] * nums[i-3];
}

int twoNegative(int* nums, int numsSize) {
    int i;
    for(i = 0; i < numsSize; ++i) {
        if(nums[i] >= 0) {
            break;
        }
    }
    if(nums[0] >= 0 || nums[1] >= 0) {
        return -1000000009;
    }
    return nums[0] * nums[1] * nums[numsSize-1];
}

int oneNegative(int* nums, int numsSize) {
    int i;
    for(i = 0; i < numsSize; ++i) {
        if(nums[i] >= 0) {
            break;
        }
    }
    if(i < 1 || i+1 >= numsSize ) {
        return -1000000009;
    }
    return nums[i] * nums[i+1] * nums[i-1];
}


int zeroNegative(int* nums, int numsSize) {
    int i;
    for(i = 0; i < numsSize; ++i) {
        if(nums[i] >= 0) {
            break;
        }
    }
    if(numsSize-3 < i ) {
        return -1000000009;
    }
    return nums[numsSize-1] * nums[numsSize-2] * nums[numsSize-3];
}

int Max(int a, int b) {
    return a > b ? a : b;
}
int comp(const void *a, const void *b) {
    return *(int*)a - *(int*)b;
}

int maximumProduct(int* nums, int numsSize){
    int ans = -1000000009;
    qsort(nums, numsSize, sizeof(int), comp);
    ans = Max(ans, threeNegative(nums, numsSize));  // (1)
    ans = Max(ans, twoNegative(nums, numsSize));    // (2)
    ans = Max(ans, oneNegative(nums, numsSize));    // (3)
    ans = Max(ans, zeroNegative(nums, numsSize));   // (4)
    return ans;
}

给你一个数组nums 和一个值val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

思路分析:

这种方法只适用对顺序要求不高的
遍历整个数组,如果遇到和给定数字一样的,就将它和数组最后一个元素交换,然后数组元素-1,指针回退1,知道没有相同元素为止

int swap(int *a, int *b) {
    int tmp = *a;
    *a = *b;
    *b = tmp;
    return tmp;
}

int removeElement(int* nums, int numsSize, int val){
    int i;
    for(i = 0; i < numsSize; ++i) {
        while(nums[i] == val) {                     // (1)  while!!!
            swap(&nums[i], &nums[numsSize-1]);      // (2) 如果发现这个数是需要删除的,就和最后一个数交换
            --numsSize;                             // (3) 最后那个数直接弹出不管了
            if(i >= numsSize) {                     // (4) 没有多余元素时,就直接跳出循环
                break;
            }
        }
    }
    return numsSize;
}

来源:三叶资源网,欢迎分享,公众号:iisanye,(三叶资源网⑤群:21414575

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

百度站内搜索
关注微信公众号
三叶资源网⑤群:三叶资源网⑤群

网站分类
随机tag
高并发http模型Signature上传视频socks5JS改写pcqq扫码自绘滚动条快递查询登录彩虹秒赞网多文件更新GIF表情包制作JS视频教程脚本蓝奏网盘会员管理系统socket5一条游走的龙获取控制台应用返回值火山安卓
最新评论