2023-07-18:给你一个正整数数组 nums,请你移除 最短 子数组(可以为 空),

使得剩余元素的 和 能被 p 整除。 不允许 将整个数组都移除。

请你返回你需要移除的最短子数组的长度,如果无法满足题目要求,返回 -1 。

子数组 定义为原数组中连续的一组元素。

输入:nums = [3,1,4,2], p = 6。

输出:1。

答案2023-07-18:

大体过程如下:

1.计算整个数组的和对p取余,得到allMod

2.初始化一个空的映射m,并将映射中键为0,值为-1。该映射用于记录前缀和的某个余数最晚出现的位置。

3.初始化一个变量ans,表示最短子数组的长度,初值为无穷大。

4.初始化一个变量curMod,表示当前的前缀和余数,初值为0。

5.初始化一个变量find,表示要查找的余数,初值为0。

6.遍历数组nums中的每个元素:

  • 将当前元素加到curMod中,并对p取余,得到当前前缀和的余数curMod

  • 计算要查找的余数find = (curMod - allMod + p) % p

  • 在映射m中查找余数为find的键,如果存在则计算当前位置与查找到的位置之差,并更新ans为较小的值。

  • 更新映射m,将当前余数curMod存储到映射中。

7.如果ans没有被更新,则返回-1,否则返回ans

代码的时间复杂度为O(n),其中n是数组nums的长度。这是因为在遍历数组nums的过程中,需要进行常数时间的操作,包括计算前缀和的余数、更新映射m等。

代码的空间复杂度为O(n),其中n是数组nums的长度。这是因为需要使用一个映射m来记录前缀和的余数及其最晚出现的位置,映射m的大小不会超过数组的长度n。此外,还需要用几个额外的变量来存储一些中间结果,这些变量的空间占用也是常数级别的,不会随着输入规模n的增大而增加。

go完整代码如下:

package main

import (
"fmt"
) func minSubarray(nums []int, p int) int {
n := len(nums)
// 求出整体的余数
allMod := 0
for _, num := range nums {
allMod = (allMod + num) % p
}
if allMod == 0 {
return 0
}
// 记录前缀和的某个余数,最晚出现的位置
// 看课!然后看接下来的代码
m := make(map[int]int)
m[0] = -1
ans := 1<<31 - 1
curMod := 0
var find int
for i := 0; i < n; i++ {
// 0...i 累加和的余数
curMod = (curMod + nums[i]) % p
// 如果p = 7,整体余数2,当前余数5,那么找之前的部分余数是3
// 如果p = 7,整体余数2,当前余数1,那么找之前的部分余数是6
// 整体变成下面的公式,可以自己带入各种情况验证
find = (curMod - allMod + p) % p
val, ok := m[find]
if ok {
if i != n-1 || val != -1 {
// 防止删掉整体!
// ...i(n-1)
ans = min(ans, i-val)
}
}
m[curMod] = i
}
if ans == 1<<31-1 {
return -1
}
return ans
} func min(a, b int) int {
if a < b {
return a
}
return b
} func main() {
nums := []int{3, 1, 4, 2}
p := 6
result := minSubarray(nums, p)
fmt.Println(result)
}

rust代码如下:

use std::collections::HashMap;

fn min_subarray(nums: Vec<i32>, p: i32) -> i32 {
let n = nums.len(); // 求出整体的余数
let all_mod: i32 = nums.iter().sum::<i32>() % p;
if all_mod == 0 {
return 0;
} // 记录前缀和的某个余数,最晚出现的位置
let mut map: HashMap<i32, i32> = HashMap::new();
map.insert(0, -1); let mut ans = i32::max_value();
let mut cur_mod = 0;
let mut find; for i in 0..n {
// 0...i 累加和的余数
cur_mod = (cur_mod + nums[i]) % p; // 如果p = 7,整体余数2,当前余数5,那么找之前的部分余数是3
// 如果p = 7,整体余数2,当前余数1,那么找之前的部分余数是6
// 整体变成下面的公式,可以自己带入各种情况验证
find = (cur_mod - all_mod + p) % p; if map.contains_key(&find) {
if i != n - 1 || map[&find] != -1 {
// 防止删掉整体!
// ...i(n-1)
ans = ans.min(i as i32 - map[&find]);
}
} map.insert(cur_mod, i as i32);
} return if ans == i32::max_value() { -1 } else { ans };
} fn main() {
let nums = vec![3, 1, 4, 2];
let p = 6;
let result = min_subarray(nums, p);
println!("{}", result);
}

c++完整代码如下:

#include <iostream>
#include <vector>
#include <unordered_map> using namespace std; int minSubarray(vector<int>& nums, int p) {
int n = nums.size();
// 求出整体的余数
int allMod = 0;
for (int num : nums) {
allMod = (allMod + num) % p;
}
if (allMod == 0) {
return 0;
}
// 记录前缀和的某个余数,最晚出现的位置
// 看课!然后看接下来的代码
unordered_map<int, int> map;
map[0] = -1;
int ans = INT_MAX;
int curMod = 0, find;
for (int i = 0; i < n; i++) {
// 0...i 累加和的余数
curMod = (curMod + nums[i]) % p;
// 如果p = 7,整体余数2,当前余数5,那么找之前的部分余数是3
// 如果p = 7,整体余数2,当前余数1,那么找之前的部分余数是6
// 整体变成下面的公式,可以自己带入各种情况验证
find = (curMod - allMod + p) % p;
if (map.find(find) != map.end()) {
if (i != n - 1 || map[find] != -1) {
// 防止删掉整体!
// ...i(n-1)
ans = min(ans, i - map[find]);
}
}
map[curMod] = i;
}
return (ans == INT_MAX) ? -1 : ans;
} int main() {
vector<int> nums = { 3, 1, 4, 2 };
int p = 6;
int result = minSubarray(nums, p);
cout << "Result: " << result << endl;
return 0;
}

c完整代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <limits.h> int minSubarray(int* nums, int numsSize, int p) {
int n = numsSize;
// 求出整体的余数
int allMod = 0;
for (int i = 0; i < n; i++) {
allMod = (allMod + nums[i]) % p;
}
if (allMod == 0) {
return 0;
}
// 记录前缀和的某个余数,最晚出现的位置
// 看课!然后看接下来的代码
int* map = (int*)malloc(sizeof(int) * p);
for (int i = 0; i < p; i++) {
map[i] = -1;
}
map[0] = -1;
int ans = INT_MAX;
int curMod = 0, find;
for (int i = 0; i < n; i++) {
// 0...i 累加和的余数
curMod = (curMod + nums[i]) % p;
// 如果p = 7,整体余数2,当前余数5,那么找之前的部分余数是3
// 如果p = 7,整体余数2,当前余数1,那么找之前的部分余数是6
// 整体变成下面的公式,可以自己带入各种情况验证
find = (curMod - allMod + p) % p;
if (map[find] != -1) {
if (i != n - 1 || map[find] != -1) {
// 防止删掉整体!
// ...i(n-1)
ans = (ans < i - map[find]) ? ans : i - map[find];
}
}
map[curMod] = i;
}
free(map);
return (ans == INT_MAX) ? -1 : ans;
} int main() {
int nums[] = { 3, 1, 4, 2 };
int p = 6;
int numsSize = sizeof(nums) / sizeof(nums[0]);
int result = minSubarray(nums, numsSize, p);
printf("Result: %d\n", result);
return 0;
}

2023-07-18:给你一个正整数数组 nums,请你移除 最短 子数组(可以为 空), 使得剩余元素的 和 能被 p 整除。 不允许 将整个数组都移除。 请你返回你需要移除的最短子数组的长度,如果的更多相关文章

  1. 给定一个整数数组nums和一个整数目标值target,请你在该数组中找出和为目标值target的那两个整数,并返回它们的数组下标。

    /** * 给定一个整数数组nums和一个整数目标值target,请你在该数组中找出和为目标值target的那两个整数,并返回它们的数组下标. * * 你可以假设每种输入只会对应一个答案.但是,数组中 ...

  2. 谷歌笔试题--给定一个集合A=[0,1,3,8](该集合中的元素都是在0,9之间的数字,但未必全部包含), 指定任意一个正整数K,请用A中的元素组成一个大于K的最小正整数。

    谷歌笔试题--给定一个集合A=[0,1,3,8](该集合中的元素都是在0,9之间的数字,但未必全部包含), 指定任意一个正整数K,请用A中的元素组成一个大于K的最小正整数. Google2009华南地 ...

  3. 刷题之给定一个整数数组 nums 和一个目标值 taget,请你在该数组中找出和为目标值的那 两个 整数

    今天下午,看了一会github,想刷个题呢,就翻出来了刷点题提高自己的实际中的解决问题的能力,在面试的过程中,我们发现,其实很多时候,面试官 给我们的题,其实也是有一定的随机性的,所以我们要多刷更多的 ...

  4. 最接近的三数之和(给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数, 使得它们的和与 target 最接近。返回这三个数的和)

    例如,给定数组 nums = [-1,2,1,-4], 和 target = 1. 与 target 最接近的三个数的和为 2. (-1 + 2 + 1 = 2). 思路:首先对数组进行排序     ...

  5. 给定长度为 n 的整数数组 nums,其中 n > 1,返回输出数组 output ,其中 output[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积。-----力扣

    给定长度为 n 的整数数组 nums,其中 n > 1,返回输出数组 output ,其中 output[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积. 示例: 输入: [1 ...

  6. 给定一个整数数组 nums 和一个目标值 target,求nums和为target的两个数的下表

    这个是来自力扣上的一道c++算法题目: 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标. 你可以假设每种输入只会对应一个答案 ...

  7. 从键盘上输入一个正整数n,请按照以下五行杨辉三角形的显示方式, 输出杨辉三角形的前n行。请采用循环控制语句来实现。

    Scanner sc=new Scanner(System.in); System.out.println("请输入一个正整数:"); int ss=sc.nextInt(); i ...

  8. 17.从键盘上输入一个正整数n,请按照以下五行杨辉三角形的显示方式, 输出杨辉三角形的前n行。请采用循环控制语句来实现。 (三角形腰上的数为1,其他位置的数为其上一行相邻两个数之和。) 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 5 1

    17.从键盘上输入一个正整数n,请按照以下五行杨辉三角形的显示方式, 输出杨辉三角形的前n行.请采用循环控制语句来实现. (三角形腰上的数为1,其他位置的数为其上一行相邻两个数之和.) 1 1 1 1 ...

  9. 在排序数组中查找元素的第一个和最后一个位置(给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。)

    示例 1: 输入: nums = [5,7,7,8,8,10], target = 8 输出: [3,4] 示例 2: 输入: nums = [5,7,7,8,8,10], target = 6 输出 ...

  10. 刷题3:给定一个数组 nums,判断 nums 中是否存在三个下标 a,b,c数相加等于targe且a,b,c不相等

    题目: 给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,下标 ,a ,b , c 对应数相加等于 targe 找出所有满足条件且不重复的三元组下标 解析: ...

随机推荐

  1. 在Linux上安装redis7

    1.检测虚拟机环境 1.1 bit检测命令:getconf LONG_BIT(建议使用64bit做开发) 1.2 gcc环境检测:gcc -v 如果不具备gcc环境,则使用yum -y install ...

  2. 目标检测(Object Detection)

    文章目录 目标检测(Object Detection) 一.基本概念 1. 什么是目标检测 2. 目标检测的核心问题 3. 目标检测算法分类 1)Tow Stage 2)One Stage 4. 目标 ...

  3. 机器视觉基本理论(opencv)

    1. 什么是图像采样 采样是按照某种时间间隔或空间间隔,将空间上连续的图像变换成离散点的操作称为图像采样 2. 什么是图像分变率 采样 得到的离散图像的尺寸称为图像分辨率.分辨率是数字图像可辨别的最小 ...

  4. MySQL高频面试题

    什么是MySQL MySQL是一个关系型数据库,它采用表的形式来存储数据.你可以理解成是Excel表格,既然是表的形式存储数据,就有表结构(行和列).行代表每一行数据,列代表该行中的每个值.列上的值是 ...

  5. 2022-09-19:给定字符串 S and T,找出 S 中最短的(连续)子串 W ,使得 T 是 W 的 子序列 。 如果 S 中没有窗口可以包含 T 中的所有字符,返回空字符串 ““。 如果有不

    2022-09-19:给定字符串 S and T,找出 S 中最短的(连续)子串 W ,使得 T 是 W 的 子序列 . 如果 S 中没有窗口可以包含 T 中的所有字符,返回空字符串 "&q ...

  6. Python-3.10安装步骤

    下载地址: https://www.python.org/ftp/python/3.10.4/python-3.10.4-amd64.exe 安装:   C:\Users\liujun>pyth ...

  7. MyBatis 在大数据量下使用流式查询进行数据同步

    通常的数据同步中,如果数据量比较少的话可以直接全量同步,默认情况下,完整的检索结果集会将其存储在内存中.在大多数情况下,这是最有效的操作方式,并且由于 MySQL 网络协议的设计,因此更易于实现.但是 ...

  8. windows下搭建docker容器环境

    下载Docker Desktop https://www.docker.com/ 安装Docker Desktop(软件默认安装c盘,若要安装到其他盘,在安装之前创建软连接再进行安装) 在自定义磁盘中 ...

  9. Cobalt Strike 连接启动教程,制作图片🐎(2)

    扫描有两种方式:arp 和 icmp 查看进程列表 攻击----生成后门-----Payload 可以生成各类语言免杀牧马---(输出:选择C或者python或者php) go.咕.com 生成c语言 ...

  10. HashMap 底层是如何实现的?

    HashMap 在不同的 JDK 版本下的实现是不同的,在 JDK 1.7 时,HashMap 底层是通过数组 + 链表实现的:而在 JDK 1.8 时,HashMap 底层是通过数组 + 链表或红黑 ...