(A卷,100分)- 计算数组中心位置(Java & JS & Python)

题目描述

给你一个整数数组nums,请计算数组的中心位置,数组的中心位置是数组的一个下标,其左侧所有元素相乘的积等于右侧所有元素相乘的积。数组第一个元素的左侧积为1,最后一个元素的右侧积为1。

如果数组有多个中心位置,应该返回最靠近左边的那一个,如果数组不存在中心位置,返回-1

输入描述

输入只有一行,给出N个正整数用空格分隔:nums = 2 5 3 6 5 6

1 <= nums.length <= 1024

1 <= nums[i] <= 10

输出描述

输出:3

解释:中心位置是3

用例

输入 2 5 3 6 5 6
输出 3
说明

题目解析

很简单的单指针操作。

应该是考察优化操作,即我们不应该每次都重新计算中心位置左边所有值和右边所有值的各自乘积,应该利用差异剔除的方式。

比如中心位置右移一格到i位置后,左边所有值的乘积left 应该变为了 left *= arr[i-1],右边所有值得乘积right 应该变为了 right /= arr[i]

JavaScript算法源码

感谢网友m0_71826536提出改进意见,本题中

1 <= nums.length <= 1024

1 <= nums[i] <= 10

也就是说单边乘积最大可以是10^1024,这个值已经远远超过了int,long范围,因此这里我们应该使用大数来处理。

JS可以使用BigInt来处理,需要注意的是BigInt类型数值只能和BigInt类型数值进行计算,否则会报错。而我们可以使用BigInt函数将Number数值转为BigInt类型,或者在字面量后面加n,比如1n

/* JavaScript Node ACM模式 控制台输入获取 */
const readline = require("readline");

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});

rl.on("line", (line) => {
  const arr = line.split(" ").map(BigInt);

  let left = 1n;
  let right = arr.reduce((p, c) => p * c) / arr[0];

  if (left === right) {
    return console.log(0);
  }

  for (let i = 1; i < arr.length; i++) {
    left *= arr[i - 1];
    right /= arr[i];

    if (left === right) return console.log(i);
  }

  return console.log(-1);
});

Java算法源码

感谢网友m0_71826536提出改进意见,本题中

1 <= nums.length <= 1024

1 <= nums[i] <= 10

也就是说单边乘积最大可以是10^1024,这个值已经远远超过了int,long范围,因此这里我们应该使用大数来处理,Java可以使用BigInteger来处理。

import java.math.BigInteger;
import java.util.Arrays;
import java.util.Scanner;

public class Main {
  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);

    Integer[] arr =
        Arrays.stream(sc.nextLine().split(" ")).map(Integer::parseInt).toArray(Integer[]::new);

    System.out.println(getResult(arr));
  }

  public static int getResult(Integer[] nums) {
    BigInteger fact = BigInteger.valueOf(1);
    for (Integer num : nums) {
      fact = fact.multiply(BigInteger.valueOf(num));
    }

    BigInteger left = BigInteger.valueOf(1);
    BigInteger right = fact.divide(BigInteger.valueOf(nums[0]));

    if (left.compareTo(right) == 0) {
      return 0;
    }

    for (int i = 1; i < nums.length; i++) {
      left = left.multiply(BigInteger.valueOf(nums[i - 1]));
      right = right.divide(BigInteger.valueOf(nums[i]));

      if (left.compareTo(right) == 0) return i;
    }

    return -1;
  }

  //  public static int getResult(Integer[] nums) {
  //    int fact = 1;
  //    for (Integer num : nums) {
  //      fact *= num;
  //    }
  //
  //    int left = 1;
  //    int right = fact / nums[0];
  //
  //    if (left == right) {
  //      return 0;
  //    }
  //
  //    for (int i = 1; i < nums.length; i++) {
  //      left *= nums[i - 1];
  //      right /= nums[i];
  //
  //      if (left == right) return i;
  //    }
  //
  //    return -1;
  //  }
}

Python算法源码

感谢网友m0_71826536提出改进意见,本题中

1 <= nums.length <= 1024

1 <= nums[i] <= 10

也就是说单边乘积最大可以是10^1024,这个值已经远远超过了int,long范围,因此这里我们应该使用大数来处理。

关于Python处理大数的说明

即Python3支持任意大的整数运算。

但是Python3整数相除时得到float小数,而float不支持任意大的数,如果数字过大会溢出,即报错如下:

python OverflowError: integer division result too large for a float_tz_zs的博客-CSDN博客

此时,我们应该使用整除 // 来保证  超大整数相除得到结果也是整数,而不是浮点数,避免溢出。

而本题,超大整数逻辑上是可以整除的。

# 输入获取
arr = list(map(int, input().split()))


# 算法入口
def getResult(arr):
    left = 1
    right = 1

    for i in arr[1:]:
        right *= i

    if left == right:
        print(0)
        return

    for i in range(1, len(arr)):
        left *= arr[i - 1]
        right //= arr[i]

        if left == right:
            print(i)
            return

    print(-1)


# 算法调用
getResult(arr)

免责声明:

1、IT资源小站为非营利性网站,全站所有资料仅供网友个人学习使用,禁止商用
2、本站所有文档、视频、书籍等资料均由网友分享,本站只负责收集不承担任何技术及版权问题
3、如本帖侵犯到任何版权问题,请立即告知本站,本站将及时予与删除下载链接并致以最深的歉意
4、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责
5、一经注册为本站会员,一律视为同意网站规定,本站管理员及版主有权禁止违规用户
6、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者和IT资源小站的同意
7、IT资源小站管理员和版主有权不事先通知发贴者而删除本文

0

评论0

站点公告

没有账号?注册  忘记密码?