【精选】JAVA入门算法题(四)

版权声明:很高兴认识你,我叫邵龙飞 原创文章,转载请注明 https://blog.csdn.net/qq_37482202/article/details/84720538

把敬业变成习惯。短期来看是为了雇主,长期来看是为了自己。

1.题目:全排列问题

这种问题在算法题中应用很多,主要思路是使用递归来求,求n个数的全排列就是把第一个数固定后求n-1个数的全排列,不断递归到只有一个数

private static void Method1() {
        disorder(array,0,array.length);
    }

    private static void disorder(int array[],int m,int n){
        if (m==n){
            for (int i=0;i<n;i++){
                System.out.print(array[i]);
            }
            System.out.println();
            return;
        }else {
            for (int i=m;i<n;i++){
                swap(array,m,i);
                disorder(array,m+1,n);
                swap(array,m,i);
            }
        }
    }

    private static void swap(int[] array,int m,int n){
        int temp=array[m];
        array[m]=array[n];
        array[n]=temp;
    }

2.题目:纸牌三角形

A,2,3,4,5,6,7,8,9 共9张纸牌排成一个正三角形(A按1计算)。要求每个边的和相等。
下图就是一种排法
    A
   9 6
  4   8
 3 7 5 2
 这样的排法可能会有很多。
 如果考虑旋转、镜像后相同的算同一种,一共有多少种不同的排法呢?
 请你计算并提交该数字。

这道题就是一个典型的全排列问题,但题目有要求说旋转、镜像算一种,那么你就要在最后的结果除以6,因为正三角旋转有3种情况,镜像有两种情况

static int[] first = new int[9];
    static int[] s = new int[9];
    static int sum = 0;

    private static void Method1() {
        seek(0);
        System.out.println(sum / 6);//6是因为有3种旋转2种翻转
    }

    private static void seek(int code) {
        if (code == 9) {
            if (s[0] + s[1] + s[3] + s[5] == s[0] + s[2] + s[4] + s[8]
                    && s[0] + s[1] + s[3] + s[5] == s[5] + s[6] + s[7] + s[8])
                sum++;
            return;
        }
        for (int i = 0; i < 9; i++) {
            if (first[i] == 0) {
                first[i] = 1;
                s[code] = i + 1;
                seek(code + 1);
                first[i] = 0;
            }
        }
    }
static int num = 0;

    private static void Method2() {
        int a[] = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9};
        f1(a, 0);
        System.out.println(num / 6);
    }

    public static void f1(int a[], int k) {
        int q, w, e;
        if (k == a.length - 1) {
            q = a[0] + a[1] + a[2] + a[3];
            w = a[3] + a[4] + a[5] + a[6];
            e = a[6] + a[7] + a[8] + a[0];
            if (q == w && w == e) num++;
        }
        for (int i = k; i < a.length; i++) {
            System.out.println(i+" "+k);
            {
                int temp = a[i];
                a[i] = a[k];
                a[k] = temp;
            }
            f1(a, k + 1);
            {
                int temp = a[i];
                a[i] = a[k];
                a[k] = temp;
            }
        }
    }

3.题目:给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的 两个 整数。你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。

示例:

给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

如果不可以组成目标数字则返回[-1,-1]

题目非常简单,只要使用for循环就能搞定

private static int[] getSum(int[] nums, int target) {
        for (int i=0;i<nums.length-1;i++){
            for (int j=i+1;j<nums.length;j++){
                if (nums[i]+nums[j]==target){
                    System.out.println(i+"  "+j);
                    return new int[]{i,j};
                }
            }
        }
        return new int[]{-1,-1};
    }

但是你会觉得两层太麻烦了,一定有办法一遍完事。这样用到了hashmap,这种数据数据查询十分快,是一种用控件换时间的数据结构,因为如果存在两个满足条件的数的话,当循环到第二个数的时候便能打印出来,这样复杂度便降到了最低了。

 public static int[] twoSum(int[] nums, int target) {
        Map<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < nums.length; i++) {
            int complement = target - nums[i];
            if (map.containsKey(complement)) {
                System.out.println(map.get(complement)+"    "+i);
                return new int[] { map.get(complement), i };
            }
            map.put(nums[i], i);
        }
        throw new IllegalArgumentException("No two sum solution");
    }

4.两数之和(二叉树)

/**
 * 给定一个二叉搜索树和一个目标结果,如果 BST 中存在两个元素且它们的和等于给定的目标结果,则返回 true。
 * 输入:
 *     5
 *    / \
 *   3   6
 *  / \   \
 * 2   4   7
 *
 * Target = 9
 *
 * 输出: True
 */
public static class TreeNode {
        int val;
        TreeNode left;
        TreeNode right;
    }

现在找寻两个数字已经从数组转换成了二叉树,但是你可以使用类似的办法,将二叉树遍历添加到数组中或者列表中,然后进行查找

private static List<Integer> integers=new ArrayList<>();
private static boolean getSum(TreeNode root, int k) {
        ergodic(root);
        if(integers.size()==1){
            if(integers.get(0)==k) return true;
            else return false;
        }
        for (int i=0;i<integers.size()-1;i++){
            for (int j=i+1;j<integers.size();j++){
                if (integers.get(i)+integers.get(j)==k){
                    return true;
                }
            }
        }
        return false;
    }

    private static void ergodic(TreeNode root) {
        if (root.left!=null){
            ergodic(root.left);
        }
        integers.add(root.val);
        if (root.right!=null){
            ergodic(root.right);
        }
    }

5.数字反转

/**
 * 给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。
 * 示例:
 * 输入: 123
 * 输出: 321
 *
 * 输入: -123
 * 输出: -321
 *
 * 输入: 120
 * 输出: 21
 */

这道题有两个点需要注意,一是要注意负数的反转,二是要注意int类型的范围问题,比如-2147483412

两种解法,一种是将大数分割成两个数进行转换,因为Integer.parseInt()的范围比较小,超出范围便会出错,另一种是借助long类型

public static int reverse(int x) {
        if (x>=0){
            char[] chars=(x+"").toCharArray();
            for (int i=0;i<chars.length/2;i++){
                char c=chars[i];
                chars[i]=chars[chars.length-i-1];
                chars[chars.length-i-1]=c;
            }
            String s=new String(chars);
            if (s.length()>=10){
                String a=s.substring(0,s.length()/2);
                String b=s.substring(s.length()/2);
                double result=Integer.parseInt(a)*Math.pow(10,b.length())+Integer.parseInt(b);
                int res=(int)result;
                if (res==Integer.MAX_VALUE){
                    return 0;
                }
                return res;
            }else {
                return Integer.parseInt(s);
            }
        }else {
            char[] chars=(x+"").toCharArray();
            for (int i=1;i<=chars.length/2;i++){
                char c=chars[i];
                chars[i]=chars[chars.length-i];
                chars[chars.length-i]=c;
            }
            String s=new String(chars);
            if (s.length()>=10){
                String a=s.substring(1,s.length()/2);
                String b=s.substring(s.length()/2);
                System.out.println(a+"   "+b+"    "+s.length()/2);
                double result=Integer.parseInt(a)*Math.pow(10,b.length())+Integer.parseInt(b);
                System.out.println(result);
                int res=(int)-result;
                if (res==Integer.MIN_VALUE){
                    return 0;
                }
                return res;
            }else {
                return Integer.parseInt(s);
            }
        }
public static int reverse(int x) {
             long z = x;
             String str = String.valueOf(Math.abs(z));
             StringBuilder conStr = new StringBuilder();
             int len = str.length();
             while( len > 0){
                 conStr.append(str.charAt(len - 1));
                 len--;
             }
             Long l = Long.parseLong(conStr.toString());
             if(l > Integer.MAX_VALUE){
                 return 0;
             }
             if(x >= 0)
                return l.intValue();
             else{
                 return -l.intValue();
             }
         }

但是你还是不满意,你觉得完全没必要这么麻烦,只要循环取个位数然后拼接到另一个数的个位数上就可以了嘛,然后中间放一个判断溢出的,怎么做呢

pop = x % 10;//取出来个位数
x /= 10;//把十位数变成个位数

temp = rev * 10 + pop;//拼接到另一个数上
rev = temp;
//循环此操作

那怎么判断是否溢出呢?如果temp=rev*10+pop溢出,那么rev>=IntMax/10,然后我们分情况进行处理

如果rev>IntMax/10,temp=rev*10+pop一定溢出

如果rev=IntMax/10,pop大于7才溢出

把逻辑写成程序

    public int reverse(int x) {
        int rev = 0;
        while (x != 0) {
            int pop = x % 10;
            x /= 10;
            if (rev > Integer.MAX_VALUE/10 || (rev == Integer.MAX_VALUE / 10 && pop > 7)) return 0;
            if (rev < Integer.MIN_VALUE/10 || (rev == Integer.MIN_VALUE / 10 && pop < -8)) return 0;
            rev = rev * 10 + pop;
        }
        return rev;
    }

漂亮!

猜你喜欢

转载自blog.csdn.net/qq_37482202/article/details/84720538
今日推荐