【备战秋招】每日一题: 2023.03.26-阿里OD机试(第一题)-切割环形数组

为了更好的阅读体检,可以查看我的算法学习博客
在线评测链接:P1117

题目内容

塔子哥是一个游戏爱好者,他喜欢用数字和算法解决各种难题。有一天,他遇到了一个有趣的问题。他手头有一个环形数组 a a a ,数组中有 n n n 个数字。

他想玩一个游戏,用两刀把它切割成两段,使得两段的数字之和相等。他可以选择在任何两个数字之间切割,但是他必须确保切割的两段都不为空。

塔子哥非常聪明,很快就意识到这是一个非常有趣的问题。他开始思考如何解决这个问题,并且尝试了很多不同的方法,还是没有想出来如何解决。

于是,塔子哥想分享这个问题并且寻求你的帮助。他想知道有多少种不同的切割方案可以使得两段数字之和相等。

输入描述

第一行输入一个正整数 n n n ,代表环形数组的元素数量。

第二行输入 n n n 个正整数 a i a_i ai,代表环形数组的元素。

1 ≤ n ≤ 1 0 5 1\leq n\leq 10^5 1n105

− 1 0 9 ≤ a i ≤ 1 0 9 -10^9\leq a_i\leq 10^9 109ai109

输出描述

一个整数,代表切割的方案数。

样例

输入

5

1 4 -2 5 2

输出

2

思路

哈希表计数

这种题目是一类经典题目。如果没见过,请跟着塔子哥的指引来:

1.LeetCode.560. 和为 K 的子数组

先把这个题搞懂。

2.P1050 华东师范大学保研机试-2022-差分计数 并查看塔子哥的题解,里面有详细的解析和代码注释。并尝试解决题解中的<拓展>部分

回到这道题,唯一要注意的地方在于:由于题目要求了两段都不能为空,所以前缀和数组不能包括开始的 0 0 0,防止出现分割出空的情况。

代码

代码写的很好了,感觉不太需要注释~

CPP

#include <bits/stdc++.h>

using namespace std;

long long NumsOfScene(vector<long long>& nums) {
    int n = nums.size(); 
    long long target = accumulate(nums.begin(), nums.end(), 0);
    if ( target%2 ) return 0;
    target /= 2;
    long long ans = 0, preSum[n+1] = {0};
    for ( int i=0;i<n;++i ) preSum[i+1] = preSum[i] + nums[i];
    unordered_map<long long,int> cnt;
    for ( int i=1;i<n+1;++i ) {
        int need = preSum[i]-target;
        auto it = cnt.find(need);
        if ( it!=cnt.end() ) ans += cnt[need];
        cnt[preSum[i]]++;
    }
    return ans;
}

int main(void) {
    int n;
    cin >> n;
    vector<long long> nums(n, 0);
    for ( long long &x:nums ) cin >> x;
    cout << NumsOfScene(nums) << endl;

    return 0;
}
//by Unsigned_Gunn

python

n = int(input().strip())
nums = list(map(int, input().strip().split(' ')))
half_sum = sum(nums)/2
dp = {}
ans = 0
cur_sum = 0
for i in range(len(nums)):
    cur_sum += nums[i]
    if cur_sum not in dp:
        dp[cur_sum] = 0
    
    tar = cur_sum-half_sum
    if tar in dp:
        ans += dp[tar]
    elif cur_sum==half_sum:
        ans += 1
    dp[cur_sum]+=1
print(ans)

Java

import java.util.HashMap;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt();
        int[] arr = new int[N];
        long sum = 0;
        for (int i = 0; i < N; i++) {
            arr[i] = sc.nextInt();
            sum+=arr[i];
        }
        if (sum % 2 != 0){
            System.out.println(0);
            return;
        }
        HashMap<Long,Integer> map = new HashMap<>();
        sum = sum/2;
        map.put((long) arr[0],1);
        long tmp = arr[0];
        long ans = 0;
        for (int i = 1; i < N; i++) {
            tmp+=arr[i];
            if (map.containsKey(tmp-sum)){
                ans+=map.get(tmp-sum);
            }
            map.put(tmp,map.getOrDefault(tmp,0)+1);
        }
        System.out.println(ans);
    }
}

Go

package main

import (
	"bufio"
	"fmt"
	"os"
)

func main() {
	sc := bufio.NewReader(os.Stdin)
	var n int
	fmt.Fscanln(sc, &n)
	nums := []int{}
	for i := 0; i < n; i++ {
		var ai int
		fmt.Fscan(sc, &ai)
		nums = append(nums, ai)
	}
	fmt.Fscanln(sc)
	test7(nums)
}

func test7(nums []int) {
	sum := 0
	for _, num := range nums {
		sum += num
	}
	if sum&1 == 1 {
		fmt.Println(0)
		return
	}
	target := sum / 2
	prefix := 0
	prefixs := []int{}
	for i := 0; i < len(nums); i++ {
		prefix += nums[i]
		prefixs = append(prefixs, prefix)
	}
	res := 0
	hashMap := map[int]int{}
	for i := 0; i < len(nums); i++ {
		pre := prefixs[i] - target
		if val, exist := hashMap[pre]; exist {
			res += val
		}
		hashMap[prefixs[i]]++
	}
	fmt.Println(res)
}

Js

function NumsOfScene(nums) {
    const n = nums.length; 
    const target = nums.reduce((acc,cur) => acc+cur, 0);
    if ( target%2 ) return 0;
    const half = target/2;
    let ans = 0, preSum = new Array(n+1).fill(0);
    for ( let i=0;i<n;++i ) preSum[i+1] = preSum[i] + nums[i];
    const cnt = new Map();
    for ( let i=1;i<n+1;++i ) {
        const need = preSum[i]-half;
        if ( cnt.has(need) ) ans += cnt.get(need);
        cnt.set(preSum[i],(cnt.get(preSum[i]) || 0) + 1);
    }
    return ans;
}

process.stdin.resume();
process.stdin.setEncoding('utf-8');
let input = '';
process.stdin.on('data', (data) => {
    input += data;
    return;
});
process.stdin.on('end', () => {
    const lines = input.trim().split('\n');
    const n = parseInt(lines[0]);
    const nums = lines[1].split(' ').map(x => parseInt(x));
    console.log(NumsOfScene(nums));
});

题目内容均收集自互联网,如如若此项内容侵犯了原著者的合法权益,可联系我: (CSDN网站注册用户名: 塔子哥学算法) 进行删除。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

塔子哥学算法

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值