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

文章目录

  • 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) {//暴力解法 写法2for (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++;}*/// 滑动窗口 双指针 写法2int 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 视间隔长度为0for(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) {//递归 约瑟夫环问题 写法1if(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 负数-1int 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.hqwc.cn/news/61385.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【自然语言处理】大模型高效微调:PEFT 使用案例

文章目录 一、PEFT介绍二、PEFT 使用2.1 PeftConfig2.2 PeftModel2.3 保存和加载模型 三、PEFT支持任务3.1 Models support matrix3.1.1 Causal Language Modeling3.1.2 Conditional Generation3.1.3 Sequence Classification3.1.4 Token Classification3.1.5 Text-to-Image Ge…

RISC-V公测平台发布 · 使用YCSB测试SG2042上的MySQL性能

实验介绍&#xff1a; YCSB&#xff08;全称为Yahoo! Cloud Serving Benchmark&#xff09;&#xff0c;该性能测试工具由Java语言编写&#xff08;在之前的MC文章中也提到过这个&#xff0c;如果没看过的读者可以去看看之前MC那一期&#xff09;&#xff0c;主要用于云端或者…

面试热题(反转链表)

给你单链表的头指针 head 和两个整数 left 和 right &#xff0c;其中 left < right 。请你反转从位置 left 到位置 right 的链表节点&#xff0c;返回 反转后的链表 。 链表的题&#xff0c;大部分都可以用指针或者递归可以做&#xff0c;指针如果做不出来的话&#xff0c;…

大模型的数据隐私问题有解了,浙江大学提出联邦大语言模型

作者 | 小戏、Python 理想化的 Learning 的理论方法作用于现实世界总会面临着诸多挑战&#xff0c;从模型部署到模型压缩&#xff0c;从数据的可获取性到数据的隐私问题。而面对着公共领域数据的稀缺性以及私有领域的数据隐私问题&#xff0c;联邦学习&#xff08;Federated Le…

[保研/考研机试] KY30 进制转换-大整数转二进制 清华大学复试上机题 C++实现

描述 将一个长度最多为30位数字的十进制非负整数转换为二进制数输出。 输入描述&#xff1a; 多组数据&#xff0c;每行为一个长度不超过30位的十进制非负整数。 &#xff08;注意是10进制数字的个数可能有30个&#xff0c;而非30bits的整数&#xff09; 输出描述&#xff…

java+springboot+mysql小区宠物管理系统

项目介绍&#xff1a; 使用javaspringbootmysql开发的小区宠物管理系统&#xff0c;系统包含超级管理员&#xff0c;系统管理员、用户角色&#xff0c;功能如下&#xff1a; 超级管理员&#xff1a;管理员管理&#xff1b;用户管理&#xff1b;宠物分类&#xff1b;宠物管理&…

Java 诊断工具 arthas-boot 安装步骤及常用命令

arthas 是 Alibaba 开源的 Java 诊断工具&#xff0c;它的特点是使用方便&#xff0c;功能强大。最重要的是&#xff0c;arthas可以监察生产环境下的项目&#xff0c;使用的过程无需重启项目。 官方文档&#xff1a;https://alibaba.github.io/arthas 一、安装 第1步&#xf…

MongoDB 备份与恢复

1.1 MongoDB的常用命令 mongoexport / mongoimport mongodump / mongorestore 有以上两组命令在备份与恢复中进行使用。 1.1.1 导出工具mongoexport Mongodb中的mongoexport工具可以把一个collection导出成JSON格式或CSV格式的文件。可以通过参数指定导出的数据项&#xff0c…

DOCKER的容器

1. 什么是Container&#xff08;容器&#xff09; 要有Container首先要有Image&#xff0c;也就是说Container是通过image创建的。 Container是在原先的Image之上新加的一层&#xff0c;称作Container layer&#xff0c;这一层是可读可写的&#xff08;Image是只读的&#xff0…

多货币多汇率跨境电子商城建设(仓储管理、网络安全)

多货币多汇率跨境电子商城建设需要考虑到多个方面&#xff0c;包括仓储管理、网络安全、货币兑换、物流配送等。以下是具体的介绍&#xff1a; 一、仓储管理 仓储管理是跨境电子商城的重要组成部分&#xff0c;需要考虑到商品的存储、管理和分拣等环节。以下是需要注意的几个…

Zookeeper 面试题

一、ZooKeeper 基础题 1.1、Zookeeper 的典型应用场景 Zookeeper 是一个典型的发布/订阅模式的分布式数据管理与协调框架&#xff0c;开发人员可以使用它来进行分布式数据的发布和订阅。 通过对 Zookeeper 中丰富的数据节点进行交叉使用&#xff0c;配合 Watcher 事件通知机…

分享21年电赛F题-智能送药小车-做题记录以及经验分享

这里写目录标题 前言一、赛题分析1、车型选择2、巡线1、OpenMv循迹2、灰度循迹 3、装载药品4、识别数字5、LED指示6、双车通信7、转向方案1、开环转向2、位置环速度环闭环串级转向3、MPU6050转向 二、调试经验分享1、循迹2、识别数字3、转向4、双车通信5、逻辑处理6、心态问题 …