day7 8-牛客67道剑指offer-JZ74、57、58、73、61、62、64、65、把字符串转换成整数、数组中重复的数字

news2024/11/24 9:32:01

文章目录

  • 1. JZ74 和为S的连续正数序列
    • 暴力解法
    • 滑动窗口(双指针)
  • 2. JZ57 和为S的两个数字
  • 3. JZ58 左旋转字符串
  • 4. JZ73 翻转单词序列
  • 5. JZ61 扑克牌顺子
  • 6. JZ62 孩子们的游戏(圆圈中最后剩下的数)
    • 迭代 模拟
    • 递归 约瑟夫环问题 找规律
  • 7. JZ64 求1+2+3+...+n
  • 8. JZ65 不用加减乘除做加法
  • 9. 把字符串转换成整数
  • 10. 数组中重复的数字
    • 哈希表
    • 原地解法

1. JZ74 和为S的连续正数序列

在这里插入图片描述

暴力解法

class Solution {
public:
    vector<vector<int> > FindContinuousSequence(int sum) {
        if(sum == 0) return vector<vector<int>>{};
        for(int i=1; i<sum; i++)
        {
            int temp = 0;
            path.clear();
            for(int j=i; j<sum; j++)
            {
                path.push_back(j);
                temp += j;
                if(temp == sum) result.push_back(path);
                if(temp > sum) break;
            }
            //result.push_back(path);
        }
        return result;
    }
    vector<int> path;
    vector<vector<int> > result;
};

至少是两个数,优化遍历的次数,数学公式计算
在这里插入图片描述

class Solution {
public:
    vector<vector<int> > FindContinuousSequence(int sum) {
        //暴力解法 写法2
        for (int n = sqrt(2 * sum); n >= 2; --n) 
        {
            if (((n & 1) == 1 && sum % n == 0) || (sum % n * 2 == n)) 
            {
                vector<int> res;
                //j用于计数,k用于遍历求值
                for (int j = 0, k = sum / n - (n - 1) / 2; j < n; j++, k++)//注意看k的求法
                    res.push_back(k);
                result.push_back(res);
                }
        }
        return result;
    }
    vector<int> path;
    vector<vector<int> > result;
};

滑动窗口(双指针)

在这里插入图片描述在这里插入图片描述

class Solution {
public:
    vector<vector<int> > FindContinuousSequence(int sum) {
        //滑动窗口
        int left = 1, right = 2, tempsum = 3;
        while(left < right)
        {
            if(tempsum == sum)//保存结果
            {
                path.clear();
                for(int i=left; i<=right; i++)
                    path.push_back(i);
                result.push_back(path);
            }
            if(tempsum < sum)//窗口右边界外扩 右移
            {
                right++;tempsum += right;
            }
            else //tempsum > sum 窗口左边界右移;tempsum = sum 窗口左边界右移 开始下一轮子结果
            {
                tempsum -= left;//新的边界值
                left++;
            }
        }
        return result;

    }
    vector<int> path;
    vector<vector<int> > result;
};

2. JZ57 和为S的两个数字

在这里插入图片描述

class Solution {
public:
    vector<int> FindNumbersWithSum(vector<int> array,int sum) {
        if(array.size() == 0) return vector<int>{};
        // 滑动窗口 双指针 写法1
        /*
        int left = 0, right = array.size()-1;
        while(left < right)
        {
            if(sum - array[left] == array[right])
            {
                result.push_back(array[left]);
                result.push_back(array[right]);
                break;
            }
            if(sum - array[left] < array[right]) right--;
            else left++;
        }
        */
        // 滑动窗口 双指针 写法2
        int left = 0, right = array.size()-1, tempsum = 0;
        while(left < right)
        {
            tempsum = array[left] + array[right];
            if(tempsum == sum)
            {
                result.push_back(array[left]);
                result.push_back(array[right]);
                return result;
            }
            else if(tempsum > sum) right--;
            else left++;
        }
        return result;
    }
    vector<int> result;
};

3. JZ58 左旋转字符串

在这里插入图片描述
先局部反转 cbafedZYX,然后整体反转XYZdefabc

#include <algorithm>
#include <type_traits>
class Solution {
public:
    string LeftRotateString(string str, int n) {
        int len = str.size();
        if(len <= 1) return str;
        else if(len < n) n %= len;
        reverse(str, 0, n-1);
        reverse(str, n, len-1);
        reverse(str, 0, len-1);
        return str;
    }
    void reverse(string& str, int start, int end)
    {
        for(int i=start, j=end; i<j; i++, j--)
        {
            swap(str[i], str[j]);
        }
    }
};

4. JZ73 翻转单词序列

在这里插入图片描述

class Solution {
public:
    string ReverseSentence(string str) {
        if(str.size() <= 1) return str;
        string result = "", temp = "";
        for(int i=0; i<str.size(); ++i)
        {
            if(str[i] == ' ')//遇到空格 把temp和之前的结果拼接
            {
                result = ' ' + temp + result;//倒序拼接
                temp = "";//更新 存下一个单词
            }
            else temp += str[i];//没有遇到空格 把整个字符串都存在temp中
        }
        if(temp.size()) // 如果temp还剩有单词 没有这一步的话示例1会返回" am a nowcoder."
            result = temp + result;
        return result;
    }
};

5. JZ61 扑克牌顺子

在这里插入图片描述

  • 排序,统计0的个数,统计所有相邻数字间隔总数。
  • 如果0的个数 = 相邻数字间隔总数,就是顺子;如果出现对子,则不是顺子。
  • 统计所有相邻数字间隔总数时,如果两个数字间隔为1,不计数。
class Solution {
public:
    bool IsContinuous(vector<int>& numbers) {
        if(numbers.size() < 5) return false;
        sort(numbers.begin(), numbers.end());
        int numOfZero = 0, numOfInner = 0;
        //如果是连续的数 排序后 两两之间间隔为1
        //比较0的个数 是否等于 统计的间隔长度 若相邻/间隔为1 视间隔长度为0
        for(int i=0; i<numbers.size() - 1; i++)
        {
            if(numbers[i] == 0) numOfZero++;
            else if(numbers[i] == numbers[i+1]) return false;//对子 不可能是顺子
            else
            {
                numOfInner += numbers[i+1] - numbers[i] - 1;//相邻数的间隔长度为0 间隔长度累加
                //numOfInner += numbers[i+1] - numbers[i] -1;//这里千万注意要减去1
            }
        }
        if(numOfZero >= numOfInner) return true;
        return false;

    }
};

6. JZ62 孩子们的游戏(圆圈中最后剩下的数)

在这里插入图片描述

迭代 模拟

class Solution {
public:
    int LastRemaining_Solution(int n, int m) {
        if(n < 1 || m < 1) return -1;
        vector<int> numbers(n,0);//标记哪个小朋友拿过礼物
        int index = -1,step = 0, count = n;
        while (count > 0) 
        {
            index++;
            if(index >= n) index = 0;//模拟环 从第一个小朋友开始
            if(numbers[index] == -1) continue;
            step++;//报数
            if(step == m)
            {
                numbers[index] = -1;
                step = 0;//下一个小朋友从头开始报数
                count--;//已经有一个小朋友拿过礼物了 环中小朋友数量-1
            }
        }
        return index;
    }
};

递归 约瑟夫环问题 找规律

在这里插入图片描述
也就是说,从f(n-1, m)当前位置来看,f(n, m)在f(n-1, m)的后m个位置。n个数字中最后剩下的数字,即去掉的数字为(m-1)%n,下一次报数是从第 m%n 个数字开始。因此,f(n-1) 和 f(n)的关系如下:

f(n-1)f(n)
0m%n
1(m+1)%n
n-2(m-2)%n

两种写法

#include <any>
class Solution {
public:
    int LastRemaining_Solution(int n, int m) {
        //递归 约瑟夫环问题 写法1
        if(n <= 0) return -1;
        return (LastRemaining_Solution(n-1, m) + m) % n;

        //递归 约瑟夫环问题 写法2
        /*
        if(n <= 0 || m < 0) return -1;
        int result = 0;
        for(int i=2; i<=n; ++i)
        {
            result = (result + m) % i;
        }
        return result;
        */
    }
};

7. JZ64 求1+2+3+…+n

在这里插入图片描述
不能用if、switch、?:等操作时,利用逻辑与的短路特性实现递归终止,也就是通过判断n是否为0来控制递归是否终止。
n递减,并且通过递归实现倒序累加和。当n = 0时,递归结束;n > 0时,递归,倒序累加求和。因此判断条件是 (n > 0) && ((result += Sum_Solution(n-1)) > 0);

class Solution {
public:
    int Sum_Solution(int n) {
        int result = n;
        (n > 0) && ((result += Sum_Solution(n-1)) > 0);
        return result;
    }
};

8. JZ65 不用加减乘除做加法

在这里插入图片描述
在这里插入图片描述
两个数异或:相当于每一位相加,而不考虑进位,产生非进位的加和结果;
两个数相与,并左移一位:相当于求得进位;
将上述两步的结果相加,什么时候进位制为0也就说明两个数相加到了最终点,也就计算结束了。

5-101,7-111
第一步:相加各位的值,不算进位,得到010,二进制每位相加就相当于各位做异或操作,101^111。
第二步:计算进位值,得到1010,相当于各位做与操作得到101,再向左移一位得到1010,(101&111)<<1。
第三步重复上述两步, 各位相加 010^1010=1000,进位值为100=(010&1010)<<1。
继续重复上述两步:1000^100 = 1100,进位值为0,跳出循环,1100为最终结果。

class Solution {
public:
    int Add(int num1, int num2) {
        //位运算 迭代
        int add = num2;// add表示进位值
        int sum = num1; // sum表示总和 
        while(add != 0)
        {
            int temp = sum ^ add;// 将每轮的无进位和与进位值做异或求和
            add = (sum & add) << 1;// 进位值是用与运算产生的
            sum = temp;// 更新sum为新的和
        }
        return sum;
    }
};

9. 把字符串转换成整数

在这里插入图片描述
要注意的两点,1.越界处理,2.正负号个数处理,越界处理用下面这种写法的时候,怎么改都只能通过95.5%的用例,最后还有两组用例没过。换成练习模式才知道原来是过不了“±5”这种例子,真的无语,加了一个统计正负号个数的判断。

#include <climits>
class Solution {
public:
    int StrToInt(string s) {
        int result = 0;
        int index = 0;
        int len = s.size();//下标索引 字符串长度
        
        //1.剔除特殊情况
        if(len == 0) return 0;

        //2.如果有前导空格就去掉,让指针往后偏移到非空格处
        while(index < len)
        {
            if(s[index] == ' ') index++;
            else break;
        }
        //如果全是空格,直接返回
        if(index >= len) return 0;

        //3.处理正负号
        int flag = 1;//正负号标志位 正数1 负数-1
        int flagnum = 0;
        //如果第一个符号是正负号的情况
        if(s[index] == '+')
        {
            index++;
            flagnum++;
        }
        if(s[index] == '-')
        {
            index++;
            flag = -1;
            flagnum++;
        }
        //最多有一个正 / 负号
        if(flagnum > 1) return 0;

        //4.有效数字部分
        while(index < len)
        {
            char c = s[index];
            //后续非法字符,截断
            if(c < '0' || c > '9') break;

            //处理越界 这种写法是结果和当前遍历的数字都进行越界处理
            if(result > INT_MAX / 10 || (result == INT_MAX / 10 && (c - '0') > INT_MAX % 10)) return INT_MAX;
            if(result < INT_MIN / 10 || (result == INT_MIN / 10 && (c - '0') > -(INT_MIN % 10))) return INT_MIN;

            result = result * 10 + flag * (c - '0');
           /*
            cout << s[index] - '0'<<endl;
            cout << flag * (s[index] - '0') <<endl;
            cout << "result:" << result <<endl;
           */
            index++;
        }
        return result;
    }
};

10. 数组中重复的数字

在这里插入图片描述

哈希表

使用了循环,循环次数为数组大小,时间复杂度为O(N)。引入额外的集合空间,空间复杂度为O(N),最坏的情况是数组中的元素都不重复。

  • 用map
#include <string>
#include <unordered_map>
class Solution {
  public:
    int duplicate(vector<int>& numbers) {
        unordered_map<int, int> m;
        for(int i=0; i<numbers.size(); i++)
        {
            m[numbers[i]]++;
            if(m[numbers[i]] >= 2) return numbers[i];            
        }
        return -1;
    }
};
  • 用vector,降低内存复杂度
#include <string>
#include <unordered_map>
class Solution {
  public:
    int duplicate(vector<int>& numbers) {
    	//哈希表 数组 直接统计频率 降低内存复杂度
        vector<int> result(numbers.size(), 0);
        for(int i=0; i<numbers.size(); i++)
        {
            result[numbers[i]]++;
            if(result[numbers[i]] >= 2) return numbers[i];
        }
        return -1;
    }
};

原地解法

在这里插入图片描述

  • 如果numbers[index] = index,第index个位置的元素也可以用numbers[numbers[index]]来表示
  • 使用了循环,循环次数为数组大小,时间复杂度为O(N)。没有引入额外的集合空间,空间复杂度为O(1)
#include <string>
#include <unordered_map>
class Solution {
  public:
    int duplicate(vector<int>& numbers) {
        //原地解法
        int index = 0;
        while (index < numbers.size()) 
        {
            if(numbers[index] == index)//第index个位置的元素=index
            {
                index++;
                continue;
            }
            else //第index个位置的元素≠index
            {
                //如果第index个位置的元素numbers[index] = index 说明元素重复
                if(numbers[index] == numbers[numbers[index]]) return numbers[index];//重复元素 返回
                else swap(numbers[index], numbers[numbers[index]]);//交换位置
            }
        }
        return -1;
    }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/861394.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CH342/CH343/CH344/CH347/CH9101/CH9102/CH9103/CH9104 Linux串口驱动使用教程

CH343 Linux串口驱动 ch343ser_linux 支持USB转串口芯片 ch342/ch343/ch344/ch347/ch9101/ch9102/ch9103/ch9104等 &#xff0c;同时该驱动配合ch343_lib库还提供了芯片GPIO接口的读写功能&#xff0c;内部EEPROM的信息配置和读取功能等。 芯片型号串口数量GPIO数量CH342F/K2C…

【Linux命令行与Shell脚本编程】第十九章 正则表达式

Linux命令行与Shell脚本编程 第十九章 正则表达式 文章目录 Linux命令行与Shell脚本编程 第十九章 正则表达式九.正则表达式9.1.正则表达式基础9.1.1.正则表达式的类型9.2.定义BRE模式9.2.1.普通文本9.2.2.特殊字符 9.2.3.锚点字符锚定行首^锚定行尾$组合锚点 9.2.4.点号字符\.…

全栈开发流程——数据表的分析与创建详解实战演示(一)

作者介绍 「作者主页」&#xff1a;雪碧有白泡泡 「个人网站」&#xff1a;雪碧的个人网站 「推荐专栏」&#xff1a; ★java一站式服务 ★ ★ React从入门到精通★ ★前端炫酷代码分享 ★ ★ 从0到英雄&#xff0c;vue成神之路★ ★ uniapp-从构建到提升★ ★ 从0到英雄&…

【Linux】UDP协议——传输层

目录 传输层 再谈端口号 端口号范围划分 认识知名端口号 两个问题 netstat与iostat pidof UDP协议 UDP协议格式 UDP协议的特点 面向数据报 UDP的缓冲区 UDP使用注意事项 基于UDP的应用层协议 传输层 在学习HTTP等应用层协议时&#xff0c;为了便于理解&#xff…

Al Go: 蒙特卡洛树搜索(MCTS)简介

目录 1. 前言 1.1 Minimax 1.2 剪枝 1.3 蒙特卡洛树搜索 1.4 为什么随机走子会可行呢&#xff1f; 2. vanilla Monte Carlo tree search 3. UCT-based trade-off between exploitation and exploration 4. MCTS基本算法流程 5. Efficiency Through Expert Policies 6…

Spring整合MyBatis(详细步骤)

Spring与Mybatis的整合&#xff0c;大体需要做两件事&#xff0c; 第一件事是:Spring要管理MyBatis中的SqlSessionFactory 第二件事是:Spring要管理Mapper接口的扫描 具体的步骤为: 步骤1:项目中导入整合需要的jar包 <dependency><!--Spring操作数据库需要该jar包…

【雕爷学编程】Arduino动手做(04)---震动模块之常闭型SW-420传感器与SW-520D倾斜模块的应用

37款传感器与模块的提法&#xff0c;在网络上广泛流传&#xff0c;其实Arduino能够兼容的传感器模块肯定是不止37种的。鉴于本人手头积累了一些传感器和执行器模块&#xff0c;依照实践出真知&#xff08;一定要动手做&#xff09;的理念&#xff0c;以学习和交流为目的&#x…

使用 Python 中的 Langchain 从零到高级快速进行工程

大型语言模型 (LLM) 的一个重要方面是这些模型用于学习的参数数量。模型拥有的参数越多,它就能更好地理解单词和短语之间的关系。这意味着具有数十亿个参数的模型有能力生成各种创造性的文本格式,并以信息丰富的方式回答开放式和挑战性的问题。 ChatGPT 等法学硕士利用 T

代码质量检查工具SonarQube

Devops流水线之SonarQube 文章目录 Devops流水线之SonarQube1. 软件功能介绍及用途2. 软件环境搭建与使用2.1 使用方法2.2 SonarQube相关属性说明2.3 Sonar配置文件内容说明 3. 使用环节4. 检查方法 1. 软件功能介绍及用途 SonarQube是一个用于代码质量管理的开源平台&#xf…

一百四十九、Kettle——Linux上安装的kettle8.2创建共享资源库时遇到的问题(持续更新中)

一、目的 在kettle8.2在Linux上安装好可以启动界面、并且可以连接MySQL、Hive、ClickHouse等数据库后开始创建共享资源库&#xff0c;但是遇到了一些问题 二、Linux系统以及kettle版本 &#xff08;一&#xff09;Linux&#xff1a;CentOS 7 英文的图形化界面模式 &#…

竞赛项目 深度学习的水果识别 opencv python

文章目录 0 前言2 开发简介3 识别原理3.1 传统图像识别原理3.2 深度学习水果识别 4 数据集5 部分关键代码5.1 处理训练集的数据结构5.2 模型网络结构5.3 训练模型 6 识别效果7 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 深度学习…

无涯教程-Perl - index函数

描述 此函数返回STR中第一次出现的SUBSTR的位置,该位置从开头(从零开始)开始,或者从POSITION(如果指定)开始。 语法 以下是此函数的简单语法- index STR, SUBSTR, POSITIONindex STR, SUBSTR返回值 失败时此函数返回-1,否则返回匹配字符串的位置(第一个字符从零开始)。 例…

Mongoose http server 例子

今天抽了点时间看了一下 mongoose的源码&#xff0c; github 地址&#xff0c;发现跟以前公司内部使用的不太一样&#xff0c;这里正好利用其 http server 例子来看一下。以前的 http message 结构体是这样的&#xff1a; /* HTTP message */ struct http_message {struct mg_…

进程的退出

进程的退出分为正常退出和异常退出&#xff1a; 正常退出 Main函数调用return进程调用exit()&#xff0c;标准c库进程调用_exit()或_Exit()&#xff0c;属于系统调用进程最后一个线程返回&#xff08;之后学到&#xff09;最后一个线程调用pthread_exit&#xff08;之后学到&…

MySQL事务:ACID特性实现原理

事务是MySQL等关系型数据库区别于NoSQL的重要方面&#xff0c;是保证数据一致性的重要手段。本文将首先介绍MySQL事务相关的基础概念&#xff0c;然后介绍事务的ACID特性&#xff0c;并分析其实现原理。 MySQL博大精深&#xff0c;文章疏漏之处在所难免&#xff0c;欢迎批评指…

基于Elman神经网络的电力负荷预测

1 案例背景 1.1 Elman神经网络概述 根据神经网络运行过程中的信息流向,可将神经网络可分为前馈式和反馈式两种基本类型。前馈式网络通过引入隐藏层以及非线性转移函数可以实现复杂的非线性映射功能。但前馈式网络的输出仅由当前输人和权矩阵决定,而与网络先前的输出结果无关。…

Postman中,既想传递文件,还想传递多个参数(后端)

需求:既想传文件又想传多个参数可以用以下方式实现

2023年的深度学习入门指南(25) - 通义千问7b

2023年的深度学习入门指南(25) - 通义千问7b 最近发生的两件事情都比较有意思&#xff0c;一个是连续开源了7b和13b模型的百川&#xff0c;对其53b闭源了&#xff1b;另一个是闭源项目通义千问开源了自己的7b模型。 下面我们就来研究下通义千问7b. 使用通义千问7b 首先安装…

LeetCode 31题:下一个排列

目录 题目 思路 代码 题目 整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。 例如&#xff0c;arr [1,2,3] &#xff0c;以下这些都可以视作 arr 的排列&#xff1a;[1,2,3]、[1,3,2]、[3,1,2]、[2,3,1] 。 整数数组的 下一个排列 是指其整数的下一个字典序…

sql高频面试题-去除最高最低的平均

面试或者笔试的过程中会设定各种各样的场景&#xff0c;在这些场景下考查我们SQL的查询能力&#xff0c;但是万变不离其宗&#xff0c;业务场景只是一个表现形式&#xff0c;抽象为SQL问题后其实基本上就是几类问题&#xff1a;计算累计、连续&#xff0c;分类TopN等。只要掌握…