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

    xiaoxiao2022-07-07  205

    一、异位词

    题目:

    /** * 给定两个字符串 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); 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; }

     

    最新回复(0)