首页 > 编程语言 >【小航的算法日记】线性枚举(二) - 统计法入门

【小航的算法日记】线性枚举(二) - 统计法入门

时间:2022-11-29 10:36:57浏览次数:50  
标签:统计法 false 小航 nums int 示例 枚举 数组 return


目录

  • ​​一、概念​​
  • ​​二、模板​​
  • ​​三、例题​​
  • ​​题:1550. 存在连续三个奇数的数组​​
  • ​​解:​​
  • ​​题:1295. 统计位数为偶数的数字​​
  • ​​解:​​
  • ​​题:540. 有序数组中的单一元素​​
  • ​​解:​​
  • ​​题:剑指 Offer 21. 调整数组顺序使奇数位于偶数前面​​
  • ​​解:​​
  • ​​题:1991. 找到数组的中间位置​​
  • ​​解:​​
  • ​​题:724. 寻找数组的中心下标​​
  • ​​题:26. 删除有序数组中的重复项​​
  • ​​解:​​
  • ​​题:1018. 可被 5 整除的二进制前缀​​
  • ​​解:​​
  • ​​题:1015. 可被 K 整除的最小整数​​
  • ​​解:​​
  • ​​题:1869. 哪种连续子字符串更长​​
  • ​​解:​​
  • ​​题:LCP 01. 猜数字​​
  • ​​解:​​
  • ​​题:1603. 设计停车系统​​
  • ​​解:​​


详情请看英雄哥的专栏,以下是Java版

一、概念

计数器、枚举

二、模板

看例题

三、例题

题:1550. 存在连续三个奇数的数组

给你一个整数数组 arr,请你判断数组中是否存在连续三个元素都是奇数的情况:如果存在,请返回 true ;否则,返回 false 。

示例 1:

输入:arr = [2,6,4,1]
输出:false
解释:不存在连续三个元素都是奇数的情况。

示例 2:

输入:arr = [1,2,34,3,4,5,7,23,12]
输出:true
解释:存在连续三个元素都是奇数的情况,即 [5,7,23] 。

提示:

1 <= arr.length <= 1000
1 <= arr[i] <= 1000

解:

解题思路:​​枚举​

AC代码:

class Solution {
public boolean threeConsecutiveOdds(int[] arr) {
int len = arr.length;
for(int i = 0; i <= len - 3; i ++) {
if((arr[i] & 1) != 0 && (arr[i+1] & 1) != 0 && (arr[i+2] & 1) != 0){
return true;
}
}
return false;
}
}

题:1295. 统计位数为偶数的数字

给你一个整数数组 nums,请你返回其中位数为 ​​偶数​​ 的数字的个数。

示例 1:

输入:nums = [12,345,2,6,7896]
输出:2
解释:
12 是 2 位数字(位数为偶数)
345 是 3 位数字(位数为奇数)
2 是 1 位数字(位数为奇数)
6 是 1 位数字 位数为奇数)
7896 是 4 位数字(位数为偶数)
因此只有 12 和 7896 是位数为偶数的数字

示例 2:

输入:nums = [555,901,482,1771]
输出:1
解释:
只有 1771 是位数为偶数的数字。

提示:

1 <= nums.length <= 500
1 <= nums[i] <= 10^5

解:

解题思路:​​枚举​

AC代码:

class Solution {
public int findNumbers(int[] nums) {
int cnt = 0;
for(int num : nums) {
if((cnt(num) & 1) == 0) cnt ++;
}
return cnt;
}
int cnt(int x) {
int cnt = 0;
while(x > 0) {
cnt ++;
x = x / 10;
}
return cnt;
}
}

题:540. 有序数组中的单一元素

给你一个仅由整数组成的有序数组,其中每个元素都会出现两次,唯有一个数只会出现一次。

请你找出并返回只出现一次的那个数。

你设计的解决方案必须满足 ​​O(log n)​​​ 时间复杂度和 ​​O(1)​​ 空间复杂度。

示例 1:

输入: nums = [1,1,2,3,3,4,4,8,8]
输出: 2

示例 2:

输入: nums =  [3,3,7,7,10,11,11]
输出: 10

提示:

1 <= nums.length <= 105
0 <= nums[i] <= 105

解:

解题思路:​​位运算​

AC代码:

class Solution {
public int singleNonDuplicate(int[] nums) {
int res = 0;
for(int num : nums) {
res ^= num;
}
return res;
}
}

解题思路:​​暴力枚举​

AC代码:

class Solution {
public int singleNonDuplicate(int[] nums) {
for(int i = 0; i < nums.length - 2; i += 2) {
if(nums[i] != nums[i + 1]) return nums[i];
}
return nums[nums.length - 1];
}
}

解题思路:​​二分​

【小航的算法日记】线性枚举(二) - 统计法入门_算法


【小航的算法日记】线性枚举(二) - 统计法入门_排序算法_02

AC代码:

class Solution {
public int singleNonDuplicate(int[] nums) {
int l = 0, r = nums.length - 1;
while(l < r) {
int mid = l + r >> 1;
if(mid % 2 != 0) mid --; // 调整mid为偶下标
if(nums[mid] == nums[mid+1]) {
l = mid + 2; // 等于后一个数,说明目标在mid后边
}else {
r = mid; // 不等于后一个数,说明目标数可能是
}
}
return nums[l];
}
}

题:剑指 Offer 21. 调整数组顺序使奇数位于偶数前面

输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数在数组的前半部分,所有偶数在数组的后半部分。

示例:

输入:nums = [1,2,3,4]
输出:[1,3,2,4]
注:[3,1,2,4] 也是正确的答案之一。

提示:

0 <= nums.length <= 50000
0 <= nums[i] <= 10000

解:

解题思路:​​双指针​

AC代码:

class Solution {
public int[] exchange(int[] nums) {
int i = 0, j = nums.length - 1;
while(i < j) {
while(i < j && (nums[i] & 1) == 1) i ++;
while(i < j && (nums[j] & 1) == 0) j --;
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
return nums;
}
}

题:1991. 找到数组的中间位置

给你一个下标从 0 开始的整数数组 ​​nums​​​ ,请你找到 ​​最左边​​​ 的中间位置 ​​middleIndex​​(也就是所有可能中间位置下标最小的一个)。

中间位置​​middleIndex​​​是满足 ​​nums[0] + nums[1] + ... + nums[middleIndex-1] == nums[middleIndex+1] + nums[middleIndex+2] + ... + nums[nums.length-1]​​ 的数组下标。

如果 ​​middleIndex == 0​​​,左边部分的和定义为 0 。类似的,如果 ​​middleIndex == nums.length - 1​​,右边部分的和定义为 0 。

请你返回满足上述条件 ​​最左边​​​ 的 ​​middleIndex​​​,如果不存在这样的中间位置,请你返回​​-1​​ 。

示例 1:

输入:nums = [2,3,-1,8,4]
输出:3
解释:
下标 3 之前的数字和为:2 + 3 + -1 = 4
下标 3 之后的数字和为:4 = 4

示例 2:

输入:nums = [1,-1,4]
输出:2
解释:
下标 2 之前的数字和为:1 + -1 = 0
下标 2 之后的数字和为:0

示例 3:

输入:nums = [2,5]
输出:-1
解释:
不存在符合要求的 middleIndex 。

示例 4:

输入:nums = [1]
输出:0
解释:
下标 0 之前的数字和为:0
下标 0 之后的数字和为:0

提示:

1 <= nums.length <= 100
-1000 <= nums[i] <= 1000

解:

解题思路:​​前缀和​

AC代码:

class Solution {
public int findMiddleIndex(int[] nums) {
int total = Arrays.stream(nums).sum();
int sum = 0;
for(int i = 0; i < nums.length; i ++) {
if(sum == total - sum - nums[i]) return i;
sum += nums[i];
}
return -1;
}
}

题:724. 寻找数组的中心下标

题:26. 删除有序数组中的重复项

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

不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

说明:

为什么返回数值是整数,但输出的答案是数组呢?

请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。

你可以想象内部操作如下:

// nums 是以“引用”方式传递的。也就是说,不对实参做任何拷贝
int len = removeDuplicates(nums);

// 在函数里修改输入数组对于调用者是可见的。
// 根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。
for (int i = 0; i < len; i++) {
print(nums[i]);
}

示例 1:

输入:nums = [1,1,2]
输出:2, nums = [1,2]
解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。

示例 2:

输入:nums = [0,0,1,1,1,2,2,3,3,4]
输出:5, nums = [0,1,2,3,4]
解释:函数应该返回新的长度 5 , 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4 。不需要考虑数组中超出新长度后面的元素。

提示:

0 <= nums.length <= 3 * 104
-104 <= nums[i] <= 104
nums 已按升序排列

解:

解题思路:​​双指针​

AC代码:

class Solution {
public int removeDuplicates(int[] nums) {
if(nums.length == 0) return 0;
int i = 0, j = 0;
for(; j < nums.length; j ++) {
if(nums[i] < nums[j]){
i ++;
if(i < j) nums[i] = nums[j];
}
}
return i + 1;
}
}

题:1018. 可被 5 整除的二进制前缀

给定由若干 0 和 1 组成的数组 A。我们定义 N_i:从 A[0] 到 A[i] 的第 i 个子数组被解释为一个二进制数(从最高有效位到最低有效位)。

返回布尔值列表 answer,只有当 N_i 可以被 5 整除时,答案 answer[i] 为 true,否则为 false。

示例 1:

输入:[0,1,1]
输出:[true,false,false]
解释:
输入数字为 0, 01, 011;也就是十进制中的 0, 1, 3 。只有第一个数可以被 5 整除,因此 answer[0] 为真。

示例 2:

输入:[1,1,1]
输出:[false,false,false]

示例 3:

输入:[0,1,1,1,1,1]
输出:[true,false,false,false,true,false]

示例 4:

输入:[1,1,1,0,1]
输出:[false,false,false,false,false]

提示:

1 <= A.length <= 30000
A[i] 为 0 或 1

解:

解题思路:​​遍历​

AC代码:

class Solution {
public List<Boolean> prefixesDivBy5(int[] nums) {
List<Boolean> res = new ArrayList<>();
int prefix = 0;
for(int num : nums) {
prefix = ((prefix << 1)+ num) % 5;
res.add(prefix == 0);
}
return res;
}
}

题:1015. 可被 K 整除的最小整数

给定正整数 k ,你需要找出可以被 k 整除的、仅包含数字 1 的最 ​​小​​ 正整数 n 的长度。

返回 n 的长度。如果不存在这样的 n ,就返回-1。

​注意: n 不符合 64 位带符号整数。​

示例 1:

输入:k = 1
输出:1
解释:最小的答案是 n = 1,其长度为 1。

示例 2:

输入:k = 2
输出:-1
解释:不存在可被 2 整除的正整数 n 。

示例 3:

输入:k = 3
输出:3
解释:最小的答案是 n = 111,其长度为 3。

提示:

1 <= k <= 105

解:

解题思路:​​数学​

AC代码:

class Solution {
public int smallestRepunitDivByK(int k) {
if(k % 2 == 0 || k % 5 == 0) return -1; // 2和5的倍数一定不行
int num = 1;
int len = 1; // 数字长度
while(num % k != 0) {
num = num % k;
num = num * 10 + 1;
len ++;
}
return len;
}
}

题:1869. 哪种连续子字符串更长

给你一个二进制字符串 s 。如果字符串中由 1 组成的 ​​最长​​​ 连续子字符串 ​​严格长于​​​ 由 0 组成的 ​​最长​​ 连续子字符串,返回 true ;否则,返回 false 。

  • 例如,s = “110100010” 中,由 1 组成的最长连续子字符串的长度是 2 ,由 0 组成的最长连续子字符串的长度是 3 。

注意,如果字符串中不存在 0 ,此时认为由 0 组成的最长连续子字符串的长度是 0 。字符串中不存在 1 的情况也适用此规则。

示例 1:

输入:s = "1101"
输出:true
解释:
由 1 组成的最长连续子字符串的长度是 2:"1101"
由 0 组成的最长连续子字符串的长度是 1:"1101"
由 1 组成的子字符串更长,故返回 true 。

示例 2:

输入:s = "111000"
输出:false
解释:
由 1 组成的最长连续子字符串的长度是 3:"111000"
由 0 组成的最长连续子字符串的长度是 3:"111000"
由 1 组成的子字符串不比由 0 组成的子字符串长,故返回 false 。

示例 3:

输入:s = "110100010"
输出:false
解释:
由 1 组成的最长连续子字符串的长度是 2:"110100010"
由 0 组成的最长连续子字符串的长度是 3:"110100010"
由 1 组成的子字符串不比由 0 组成的子字符串长,故返回 false 。

提示:

1 <= s.length <= 100
s[i] 不是 '0' 就是 '1'

解:

解题思路:​​遍历字符串​

AC代码:

class Solution {
public boolean checkZeroOnes(String s) {
int len0 = 0, len1 = 0;
int max0 = 0, max1 = 0;
for(char ss : s.toCharArray()) {
if(ss == '0') {
len0 ++;
len1 = 0;
}else {
len1 ++;
len0 = 0;
}
max0 = Math.max(len0, max0);
max1 = Math.max(len1, max1);
}
return max1 > max0;
}
}

题:LCP 01. 猜数字

小A 和 小B 在玩猜数字。小B 每次从 1, 2, 3 中随机选择一个,小A 每次也从 1, 2, 3 中选择一个猜。他们一共进行三次这个游戏,请返回 小A 猜对了几次?

输入的​​guess​​​数组为 小A 每次的猜测,​​answer​​​数组为 小B 每次的选择。​​guess​​​和​​answer​​的长度都等于3。

示例 1:

输入:guess = [1,2,3], answer = [1,2,3]
输出:3
解释:小A 每次都猜对了。

示例 2:

输入:guess = [2,2,3], answer = [3,2,1]
输出:1
解释:小A 只猜对了第二次。

限制:

guess 的长度 = 3
answer 的长度 = 3
guess 的元素取值为 {1, 2, 3} 之一。
answer 的元素取值为 {1, 2, 3} 之一。

解:

解题思路:​​枚举​

AC代码:

class Solution {
public int game(int[] guess, int[] answer) {
int cnt = 0;
for(int i = 0; i < guess.length; i ++) {
if(guess[i] == answer[i]) cnt ++;
}
return cnt;
}
}

题:1603. 设计停车系统

请你给一个停车场设计一个停车系统。停车场总共有三种不同大小的车位:大,中和小,每种尺寸分别有固定数目的车位。

请你实现 ParkingSystem 类:

  • ParkingSystem(int big, int medium, int small) 初始化 ParkingSystem 类,三个参数分别对应每种停车位的数目。
  • bool addCar(int carType) 检查是否有 carType 对应的停车位。 carType 有三种类型:大,中,小,分别用数字 1, 2 和 3 表示。​​一辆车只能停在​​ carType 对应尺寸的停车位中。如果没有空车位,请返回 false ,否则将该车停入车位并返回 true 。

示例 1:

输入:
["ParkingSystem", "addCar", "addCar", "addCar", "addCar"]
[[1, 1, 0], [1], [2], [3], [1]]
输出:
[null, true, true, false, false]

解释:
ParkingSystem parkingSystem = new ParkingSystem(1, 1, 0);
parkingSystem.addCar(1); // 返回 true ,因为有 1 个空的大车位
parkingSystem.addCar(2); // 返回 true ,因为有 1 个空的中车位
parkingSystem.addCar(3); // 返回 false ,因为没有空的小车位
parkingSystem.addCar(1); // 返回 false ,因为没有空的大车位,唯一一个大车位已经被占据了

提示:

0 <= big, medium, small <= 1000
carType 取值为 1, 2 或 3
最多会调用 addCar 函数 1000 次

解:

解题思路:​​枚举​

AC代码:

class ParkingSystem {
int big, medium, small;

public ParkingSystem(int big, int medium, int small) {
this.big = big;
this.medium = medium;
this.small = small;
}

public boolean addCar(int carType) {
if (carType == 1) {
if (big > 0) {
big--;
return true;
}
} else if (carType == 2) {
if (medium > 0) {
medium--;
return true;
}
} else if (carType == 3) {
if (small > 0) {
small--;
return true;
}
}
return false;
}
}


标签:统计法,false,小航,nums,int,示例,枚举,数组,return
From: https://blog.51cto.com/u_15895329/5894202

相关文章

  • 【小航的算法日记】进制转换(二) - 进阶
    目录​​一、概念​​​​二、模板​​​​三、例题​​​​题:202.快乐数​​​​解:​​​​题:168.Excel表列名称​​​​解:​​​​题:171.Excel表列序号​​​​解:​​......
  • 【小航的算法日记】进制转换(一) - 入门
    目录​​一、概念​​​​二、模板​​​​三、例题​​​​题:剑指Offer15.二进制中1的个数​​​​解:​​​​题:258.各位相加​​​​解:​​​​题:1290.二进制链表转......
  • 【小航的算法日记】字符串算法(二) - 字符串比较
    目录​​一、概念​​​​二、模板​​​​三、例题​​​​题:剑指Offer05.替换空格​​​​解:​​​​题:面试题10.05.稀疏数组搜索​​​​解:​​​​题:1763.最长的......
  • 【小航的算法日记】线段树
    本内容取经于:https://leetcode.cn/problems/my-calendar-i/solution/by-lfool-xvpv/一、概念概念区分:线段树解决的是「区间和」的问题,且该「区间」会被修改前缀和解决的是......
  • Freesql ORM 多条件枚举Sum
    反射枚举desc建拉姆达查询sum///<summary>///创建lambda表达式:p=>p.propertyName///</summary>///<typeparamname="T"></ty......
  • 【小航的算法日记】字符串
    目录​​一、概念​​​​二、模板​​​​三、例题​​​​题:344.反转字符串​​​​解:​​​​题:541.反转字符串II​​​​解:​​​​题:剑指Offer05.替换空格​​​......
  • 【小航的算法日记】哈希
    一、概念哈希表、哈希函数、哈希碰撞二、模板三、例题题:242.有效的字母异位词给定两个字符串s和t,编写一个函数来判断t是否是s的字母异位词。注意:若s和t中每个......
  • 【小航的算法日记】图论
    目录​​一、概念、模板​​​​存图方式:​​​​1.邻接矩阵​​​​2.邻接表​​​​3.类​​​​算法:​​​​拓扑排序:​​​​最短路问题:​​​​1.Floyd「多源汇最短路......
  • 枚举
    枚举枚举的作用:"是为了做信息的标志和信息的分类"。枚举类都是继承了枚举类型:java.lang.Enum枚举都是最终类,不可以被继承。构造器都是私有的,枚举对外不能创建对象。枚举......
  • 06.枚举与模式匹配
    定义枚举IP地址:IPv4、IPv6enumIpAddrKindf{V4,V6}枚举值letfour=lpAddrKind::V4;letsix=lpAddrKind::V6;将数据附加到枚举的变体中优点:......