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

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

时间:2023-07-18 22:14:42浏览次数:44  
标签:map 07 nums int ans 数组 移除 余数 find

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;
}

在这里插入图片描述

标签:map,07,nums,int,ans,数组,移除,余数,find
From: https://www.cnblogs.com/moonfdd/p/17564249.html

相关文章

  • 写代码,找出两个字符串数组中相同的字符串存到新的字符串中,使用hashset
    时间复杂度:O(m+n)packageleetcode.arrayAndList;importjava.util.ArrayList;importjava.util.HashSet;importjava.util.Set;publicclassCommentStr{publicstaticvoidmain(String[]args){ArrayListans=newArrayList();//两个字符......
  • 20230718巴蜀暑期集训测试总结
    T1做了\(3h\),时间复杂度不对,小样例都还有一个没过。考虑容斥,不连通的情况枚举\(1\)号点所在连通块。设\(f_{S,i}\)表示\(S\)连通且选了\(i\)条边的方案数。设\(inb_s\)表示\(S\)内部的边数。那么有转移:\[f_{S,i}=\binom{inb_S}i-\sum_{T\subsetneqqS,1\inT}......
  • hdu 2227 Find the nondecreasing subsequences (树状数组+dp+离散化)
    题意:给定一个长度为n(n<=100000)的整数序列,求其中的递增序列的个数。对于某些序列中的递增序列的个数是可以用dp来求解的,其状态转移方程为:dp[i]=sum(dp[j])+1,j<i&&a[j]<a[i]根据状态转移方程可以得知这样dp的时间复杂度为O(n^2),而对于题目给定的10^6的数量级来说,这样......
  • 07_预处理
    预处理动态库和静态库库:将源文件生成的二进制文件只需要链接即可生成可执行文件制作静态库gcc-cfun.c-ofun.oarrclibtestlib.afun.o使用静态库库和工程在同一目录下gccmain.clibtestlib.a静态库libtestlib.a以lib开头.a结尾中间才是库的名称testlib......
  • js 判断对象数组里面是否存在重复数据
    可以使用JavaScript来判断对象数组中是否存在重复数据。下面是一种常见的解决方法:functionhasDuplicate(array){constseen=newSet();for(leti=0;i<array.length;i++){constobjString=JSON.stringify(array[i]);if(seen.has(objString))......
  • 8-102-(LeetCode- 207&210) 课程表
    1.题目 读题  考查点 2.解法思路这个问题可以用图论的方法来解决,具体思路如下:将课程和先修课程看作有向图的节点和边,如果要学习课程ai,则必须先学习课程bi,表示为bi->ai。判断图中是否存在环,如果存在环,则说明有些课程无法完成,返回false;如果不存在环,则说明所有课程都......
  • 数仓知识07:数据增量更新的几种方式
    数仓知识07:数据增量更新的几种方式1、增量更新的几种方式增量更新的本质,其实是获取源表中数据变化的情况(增、删、改),然后将源表中发生的变化同步至目标表中。不同的方式,获取源表中数据变化的情况不一样,受技术的限制、表结构的限制,某些方式可能无法获取到完整的数据变化情况,因......
  • Day11(2023.07.18)
    行程8:45    到达上海市信息安全测评认证中心(黄浦区陆家浜路1308号)9:00  改文件11:30--13:00   吃饭休息13:00 创建项目,熟悉软件,生成报告等..17:00      下班......
  • python 删除数组 空值
    Python删除数组空值的步骤在Python中,删除数组中的空值可以通过以下步骤完成。下面是一个简单的流程表格,显示了实现这个功能的步骤和相应的代码:步骤代码1.导入必要的模块和库importnumpyasnp2.创建一个包含空值的数组arr=np.array(['','hello','','world'......
  • python将16进制数组转换成字符串
    Python将16进制数组转换成字符串在编程中,我们经常需要处理不同的数据类型和格式。其中,16进制是一种十分常见的数据表示方式,特别在加密和通信领域中经常用到。本篇文章将介绍如何使用Python将16进制数组转换成字符串,并提供相应的代码示例。什么是16进制?在计算机科学中,16进制(Hexad......