【精选】JAVA算法题(二十)

博客围绕Java算法题展开,包含异位词、二叉树的路径、回旋镖、数字加和等题目。对于异位词,介绍了排序比对、用Map统计等方法;二叉树路径题用递归遍历;回旋镖需判断三点不共线;数字加和给出常规循环法及进阶无循环递归的解法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、异位词

题目:

/**
 * 给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的一个字母异位词。
 *
 * 示例 1:
 * 输入: s = "anagram", t = "nagaram"
 * 输出: true
 *
 * 示例 2:
 * 输入: s = "rat", t = "car"
 * 输出: false
 *
 * 说明:
 * 你可以假设字符串只包含小写字母。
 */

 大体意思是说两个字符串,把其中一个字符串中的一个或几个字母换个位置就和另一个字符串相等了。

既然换字母就能让两个字符串相等,那么他们就有相同的字母,可以先排序再比对。

    public static boolean method1(String s, String t) {
        char[] sChars = s.toCharArray();
        char[] tChars = t.toCharArray();
        Arrays.sort(sChars);
        Arrays.sort(tChars);
        return String.valueOf(sChars).equals(String.valueOf(tChars));
    }

用Map对每个字母的出现次数进行统计再检查另一个字符串,消费,看最后Map是否为空

    public static boolean method2(String s, String t) {
        Map<Character, Integer> map = new HashMap<>();
        for (char ch : s.toCharArray()) {
            map.put(ch, map.getOrDefault(ch, 0) + 1);
        }
        for (char ch : t.toCharArray()) {
            Integer count = map.get(ch);
            if (count == null) {
                return false;
            } else if (count > 1) {
                map.put(ch, count - 1);
            } else {
                map.remove(ch);
            }
        }
        return map.isEmpty();
    }

把字符串转换成Ascll码当数组下标使,同样是统计数量进行比对。

    public static boolean method3(String s, String t) {
        int[] sCounts = new int[26];
        int[] tCounts = new int[26];
        for (char ch : s.toCharArray()) {
            sCounts[ch - 'a']++;
        }
        for (char ch : t.toCharArray()) {
            tCounts[ch - 'a']++;
        }
        for (int i = 0; i < 26; i++) {
            if (sCounts[i] != tCounts[i]) {
                return false;
            }
        }
        return true;
    }

二、二叉树的路径

题目:

/**
 * 给定一个二叉树,返回所有从根节点到叶子节点的路径。
 * 说明: 叶子节点是指没有子节点的节点。
 *
 * 示例:
 * 输入:
 * <p>
 *     1
 *  /   \
 * 2     3
 *  \
 *   5
 *
 * 输出: ["1->2->5", "1->3"]
 * 解释: 所有根节点到叶子节点的路径为: 1->2->5, 1->3
 */
public class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;

    TreeNode(int x) {
        val = x;
    }
}

这题一看就需要遍历树的知识了,而且用递归更为简单,不断保留当前已经遍历的路径并不断添加新的节点,直到到达叶子节点才加入list.

    List<String> res = new ArrayList<String>();
    public List<String> method1(TreeNode root) {
        if(root == null)
            return res;
        if(root.left == null && root.right == null){
            res.add(root.val + "");
        }
        if(root.left != null){
            fun(root.left, root.val + "");
        }
        if(root.right != null){
            fun(root.right, root.val + "");
        }

        return res;
    }

    /**
     * 递归判断当前节点是不是叶子节点
     * 参数 root 为当前节点,str 为该节点前的路径
     * 若遇到叶子节点,则加入res中;若非叶子节点,则继续往下走
     */
    public void fun(TreeNode root, String str){
        if(root == null)
            return;
        if(root.left == null && root.right == null)
            res.add(str + "->" + root.val);
        if(root.left != null){
            fun(root.left, str + "->" + root.val);
        }
        if(root.right != null){
            fun(root.right, str + "->" + root.val);
        }
    }

三、回旋镖

题目:

/**
 * 回旋镖定义为一组三个点,这些点各不相同且不在一条直线上。
 * 给出平面上三个点组成的列表,判断这些点是否可以构成回旋镖。
 *
 * 示例 1:
 * 输入:[[1,1],[2,3],[3,2]]
 * 输出:true
 *
 * 示例 2:
 * 输入:[[1,1],[2,2],[3,3]]
 * 输出:false
 */

 关键点:三点不共线,这个证明我们初中都学过,如何判断我写在注释里面了,需要判断的异常条件便是同时两个点在X轴或者Y轴。

    /**
     * 三点共线条件
     * A(x1,y1)、B(x2,y2)、C(x3,y3)
     * AB斜率:kAB=(y2-y1)/(x2-x1)
     * BC斜率:kBC=(y3-y2)/(x3-x2)
     * 计算结果可得:kAB=kBC。
     */
    public static boolean isBoomerang(int[][] points) {
        if ((points[0][0]==points[1][0]&&points[0][1]==points[1][1])||
                (points[0][0]==points[2][0]&&points[0][1]==points[2][1])||
                (points[1][0]==points[2][0]&&points[1][1]==points[2][1])){
            return false;
        }
        double x2x1=points[1][0]-points[0][0];
        double x3x2=points[2][0]-points[1][0];
        double y2y1=points[1][1]-points[0][1];
        double y3y2=points[2][1]-points[1][1];
        double kAB=0,kBC=0;
        if (x2x1==0){
            kAB=Integer.MAX_VALUE;
        }else {
            kAB=y2y1/x2x1;
        }
        if (x3x2==0){
            kBC=Integer.MAX_VALUE;
        }else {
            kBC=y3y2/x3x2;
        }
        if ((kAB==Integer.MAX_VALUE&&kBC==0)||(kAB==0&&kBC==Integer.MAX_VALUE)){
            return true;
        }
        if (kAB==kBC){
            return false;
        }
        return true;
    }

四、数字加和

题目:

/**
 * 给定一个非负整数 num,反复将各个位上的数字相加,直到结果为一位数。
 *
 * 示例:
 * 输入: 38
 * 输出: 2
 * 解释: 各位相加的过程为:3 + 8 = 11, 1 + 1 = 2。 由于 2 是一位数,所以返回 2。
 *
 * 进阶:
 * 你可以不使用循环或者递归,且在 O(1) 时间复杂度内解决这个问题吗?
 */

最笨的方法就是循环,不断把每一位取出来放到list里面,最后加和,你也可以自己定义变量在分离每一位的时候就进行加和并最后进行赋值操作。

    public static int method1(int num) {
        ArrayList<Integer> integers=new ArrayList<>();
        while (num>9){
            while (num!=0){
                integers.add(num%10);
                num/=10;
            }
            for (int a:integers){
                num+=a;
            }
            integers.clear();
        }
        return num;
    }

当然我们要挑战一下进阶条件,不适用循环和递归,并在时间复杂度0(1)解决这个问题,那这就需要找寻规律了。

假如一个三位数'abc',其值大小为s1 = 100 * a + 10 * b + 1 * c,经过一次各位相加后, 变为s2 = a + b + c,减小的差值为(s1 -s2) = 99 * a + 9 * b,差值可以被9整除,每一个循环都这样,缩小了9的倍数。 当num小于9,即只有一位时,直接返回num,大于9时,如果能被9整除,则返回9(因为不可能返回0也不可能返回两位数及以上的值), 如果不能被整除,就返回被9除的余数。

    public static int method2(int num) {
        return num==0?0:num%9==0?9:num%9;
    }

很简洁,下面这种意思一样

    public static int method3(int num) {
        if (num > 9){
            num = num % 9;
            if(num == 0){
                return 9;
            }
        }
        return num;
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

幽蓝丶流月

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

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

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

打赏作者

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

抵扣说明:

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

余额充值