小和问题,Java实现

题目:给你一个数组,请输出这个数组中的小和是多少?

小和:在一个数组中,每一个数的左边的数比当前数小的数累加起来
eg:[1,3,4,2,5]
比1小:无
比3小:1
比4小:1,3
比2小:1
比5小:1,3,4,2
小和:1+1+3+1+1+3+4+2=16

方法一:暴力枚举
public class demo {
    public static void main(String[] args) {
        int[] nums = {5,3,1,2,6};
        int sum = getSmallSum(nums);
        System.out.println(sum);
    }

    /**
     * 得到小和
     * @param nums - 需要求小和的数组
     * */
    public static int getSmallSum(int[] nums) {
    	if(nums.length<=1){//如果数组长度小于1,那么数组中的元素只有1个或0个,那么不产生小和
    		return 0;
    	}
        int sum=0;
        for(int i =0 ;i<nums.length;i++){
            for(int j =0 ;j<i;j++){
                if(nums[j]<nums[i]){//左边的数比这个数小
                    sum += nums[j];
                }
            }
        }
        return sum;
    }
}
方法二:分治
public class demo {
    public static void main(String[] args) {
        int[] nums = {5, 3, 1, 2, 6};
        int start = 0;
        int end = nums.length - 1;
        //递归
        int sum = process(nums, start, end);
        System.out.println(sum);
    }

    /**
     * @param nums  - 需要递归的数组
     * @param start - 开始下标
     * @param end   - 结束下标
     * @return int - 返回在递归过程中产生的小和
     */
    public static int process(int[] nums, int start, int end) {
    	if(nums.length<=1){
    		return 0;
    	}
        if (start == end) {
            return 0;
        }
        //中点
        int middle = start + ((end - start) >> 1);

        /*
         * process(nums, start, middle)---左边递归产生的小和
         * process(nums, middle + 1, end)---右边递归产生的小和
         * getSmallSum(nums, start, middle, end)----归并过程产生的小和
         * */
        return process(nums, start, middle)+process(nums, middle + 1, end)+getSmallSum(nums, start, middle, end);
    }

    /**
     * 得到小和
     *  @param nums   - 需要求小和的数组
     * @param start  - 开始下标
     * @param middle - 中间下标
     * @param end    - 结束下标
     */
    public static int getSmallSum(int[] nums, int start, int middle, int end) {
        //定义一个新的数组
        int[] newArray = new int[end + 1];
        //从传入数组的开始下标开始改变原数组的顺序
        int i = start;
        //从传入的数组开始下标开始进行比较
        int tempLeft = start;
        int tempRight = middle + 1;
        //小和
        int res = 0;
        while (tempLeft <= middle && tempRight <= end) {
            //如果左边的指针小于右边的指针所代表的数,那么产生小和,比左边指针大的个数为end-tempRight+1
            res += nums[tempLeft] < nums[tempRight] ? nums[tempLeft]*(end-tempRight+1)  : 0;
            newArray[i++] = nums[tempLeft] < nums[tempRight] ? nums[tempLeft++] : nums[tempRight++];
        }
        while(tempLeft <= middle){
            newArray[i++] = nums[tempLeft++];
        }
        while(tempRight <= end){
            newArray[i++] = nums[tempRight++];
        }
        //改变原数组的顺序
        for(i =start ; i<newArray.length;i++){
            nums[i]=newArray[i];
        }
        return res;
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值