牛客杂记——6.2

总结

  • 基础知识
  • 编程
    • 汽水瓶
    • 数组中的逆序对

基础知识

1、java中synchronized关键字可以对对象加互斥锁
2、在子类构造方法中使用super()显示调用父类的构造方法,super()必须写在子列构造方法的第一行,否则编译不通过
3、声明抽象方法,不可写出大括号,abstract只能修饰方法和类,抽象方法无方法体,有无方法体看有无大括号

编程

汽水瓶

链接:https://www.nowcoder.com/questionTerminal/fe298c55694f4ed39e256170ff2c205f
来源:牛客网

有这样一道智力题:“某商店规定:三个空汽水瓶可以换一瓶汽水。小张手上有十个空汽水瓶,她最多可以换多少瓶汽水喝?”答案是5瓶,方法如下:先用9个空瓶子换3瓶汽水,喝掉3瓶满的,喝完以后4个空瓶子,用3个再换一瓶,喝掉这瓶满的,这时候剩2个空瓶子。然后你让老板先借给你一瓶汽水,喝掉这瓶满的,喝完以后用3个空瓶子换一瓶满的还给老板。如果小张手上有n个空汽水瓶,最多可以换多少瓶汽水喝?

牛客杂记——6.2_第1张图片
两种方法
递归:


import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        while (in.hasNextInt()) {// 注意,如果输入是多个测试用例,请通过while循环处理多个测试用例
            int a = in.nextInt();
            if( a== 0){
                break;
            }
            int b = findNum(a);
            System.out.println(b);
        }
    }
    public static int findNum(int num){
        if(num == 3 || num == 2){
            return 1;
        }
        int count = 0;
        count = num/3;
        num = count + num % 3;
        count += findNum(num);
        return count;
    }
}

循环

import java.util.Scanner;
public class Main {
    public static int drink(int n) {
        int total = 0;//饮料总数
//当大于两个空瓶的时候才可以换饮料
        while(n > 2) {
//n/3-->能够换来的饮料
            total = total+n/3;
//新的空瓶子个数--》n%3可能会不能整除
            n = n/3 + n%3;
        }
//如果n==2,说明有两个空瓶可以喝商家借一瓶饮料
        if(n == 2) {
            total = total + 1;
        }
        return total;
    }
    public static void main(String[] args){
//创建键盘录入对象
        Scanner sc=new Scanner(System.in);
        int n;
        while(sc.hasNext())
        {
            n=sc.nextInt();
            System.out.println(drink(n));
        }
    }
}

数组中的逆序对

链接:https://www.nowcoder.com/questionTerminal/bb06495cc0154e90bbb18911fd581df6
来源:牛客网

有一组数,对于其中任意两个数组,若前面一个大于后面一个数字,则这两个数字组成一个逆序对。请设计一个高效的算法,计算给定数组中的逆序对个数。

给定一个int数组A和它的大小n,请返回A中的逆序对个数。保证n小于等于5000。

测试样例:
在这里插入图片描述
1、暴力循环:

import java.util.*;

public class AntiOrder {
    public int count(int[] A, int n) {
         int count = 0;
        for (int i = 0; i < n ; i++) {

            for (int j = i+1; j < n; j++) {
                if(A[i] > A[j]){
                    count++;
                }
            }

        }
        return count;
    }
}

2、递归
左右分治

public class AntiOrder {
    public int count(int[] A, int n) {
        if (A == null || n == 0) {
            return 0;
        }
        return mergeSortRecursion(A, 0, n - 1);
    }
    public static int mergeSortRecursion(int[] arr, int l, int r) {
        if (l == r) {
            return 0;
        }
        int mid = (l + r) / 2;
//逆序对的总数=左边数组中的逆序对的数量+右边数组中逆序对的数量+左右结合成新的顺序数组时中出现的逆序对的数量;
        return mergeSortRecursion(arr, l, mid) + mergeSortRecursion(arr, mid + 1, r) +
                merge(arr, l, mid, r);
    }
    public static int merge(int[] arr, int left, int mid, int right) {
        int[] temp = new int[right - left + 1];
        int index = 0;
        int i = left;
        int j = mid + 1;
        int inverseNum = 0;// 新增,用来累加数组逆序对
        while (i <= mid && j <= right) {
            if (arr[i] <= arr[j]) {
                temp[index++] = arr[i++];
            } else {
// 当前一个数组元素大于后一个数组元素时,累加逆序对
                inverseNum += (mid - i + 1);
                temp[index++] = arr[j++];
            }
        }
        while (i <= mid) {
            temp[index++] = arr[i++];
        }
        while (j <= right) {
            temp[index++] = arr[j++];
        }
        for (int k = 0; k < temp.length; k++) {
            arr[left++] = temp[k];
        }
        return inverseNum;
    }
}

你可能感兴趣的:(牛客)