LeetCode 657. Robot Return to Origin(Java相同类型的包装类对象之间值的比较需要注意的地方)

本文旨在分享刷LeetCode 657. Robot Return to Origin时遇到的大坑:Java相同类型的包装类对象之间值的比较问题。

题目一个关于二维平面的机器人能否返回原点的问题:

There is a robot starting at position (0, 0), the origin, on a 2D plane. Given a sequence of its moves, judge if this robot ends up at (0, 0)after it completes its moves.

The move sequence is represented by a string, and the character moves[i] represents its ith move. Valid moves are R (right), L (left), U (up), and D (down). If the robot returns to the origin after it finishes all of its moves, return true. Otherwise, return false.

Note: The way that the robot is "facing" is irrelevant. "R" will always make the robot move to the right once, "L" will always make it move left, etc. Also, assume that the magnitude of the robot's movement is the same for each move.

思路也很简单,就是判断上下左右移动的步数,如果向上等于向下,向左等于向右,就可以回到原点,否则就不可以。利用HashMap记录一下U、D、R、L的个数,然后判断是否相等即可。

错误的解答如下:

class Solution {
    public boolean judgeCircle(String moves) {
        System.out.println(moves.length());
        if(moves.length()==0){
            return true;
        }
        if(moves.length()%2!=0){
            return false;
        }
        HashMap<Character,Integer> map = new HashMap<Character,Integer>();
        for(int i=0;i<moves.length();i++){
            if(!map.containsKey(moves.charAt(i))){
                map.put(moves.charAt(i),1);
            }else{
                 map.put(moves.charAt(i),map.get(moves.charAt(i))+1);
            }
        }
        System.out.println("U="+(map.get('U')));
        System.out.println("D="+(map.get('D')));
        System.out.println("R="+(map.get('R')));
        System.out.println("L="+(map.get('L')));
        
        System.out.println(map.get('U')==map.get('D'));
        System.out.println(map.get('R')==map.get('L'));                   
        if(map.get('U')==map.get('D') && map.get('R')==map.get('L')){
            return true;
        }else{
            return false;
        }
    }
}

提交以后显示不正确,输出打印结果如下:

感觉莫名其妙,加入以下输出信息以后,确定是两个Integer变量比较的时候出问题了。

Integer类型的数据在-128~127范围内用==和equals比较的结果是一样的,超出此范围才会出现差异。

为什么会出现这种情况呢?Integer是int对应的包装类,它有一个int类型的字段存储数据,并且提供了基本操作,比如数学运算、int和字符串之间转换等。在Java 5中,引入了自动装箱和自动拆箱功能(boxing/unboxing),Java可以根据上下文,自动进行转换,极大地简化了相关编程。

关于Integer的值缓存,这涉及Java 5中另一个改进。构建Integer对象的传统方式是直接调用构造器,直接new一个对象。但是根据实践,我们发现大部分数据操作都是集中在有限的、较小的数值范围,因而,在Java 5中新增了静态工厂方法valueOf,在调用它的时候会利用一个缓存机制,带来了明显的性能改进。按照Javadoc,这个值默认缓存是-128到127之间。

这确实是一个大坑,正如《阿里巴巴Java开发手册》中强制规约的一样:所有相同类型的包装类对象之间值的比较,全部使用equals方法

修改以后的代码可以获得通过,如下:

class Solution {
    public boolean judgeCircle(String moves) {
        if(moves.length()==0){
            return true;
        }
        if(moves.length()%2!=0){
            return false;
        }
        HashMap<Character,Integer> map = new HashMap<Character,Integer>();
        for(int i=0;i<moves.length();i++){
            if(!map.containsKey(moves.charAt(i))){
                map.put(moves.charAt(i),1);
            }else{
                 map.put(moves.charAt(i),map.get(moves.charAt(i))+1);
            }
        }
        if(!map.containsKey('U')){
            map.put('U',0);
        }
        if(!map.containsKey('D')){
            map.put('D',0);
        }
        if(!map.containsKey('R')){
            map.put('R',0);
        }
        if(!map.containsKey('L')){
            map.put('L',0);
        }
        if(map.get('U').equals(map.get('D')) && map.get('R').equals(map.get('L'))){
            return true;
        }
        return false;
    }
}

其实这道题还有稍微简单点的解法,可以通过判断机器人在水平和垂直方向有没有相对移动,代码如下:

class Solution {
    public boolean judgeCircle(String moves) {
        System.out.println(moves.length());
        if(moves.length()==0){
            return true;
        }
        if(moves.length()%2!=0){
            return false;
        }
        int h = 0;
        int v = 0;
        for(int i=0;i<moves.length();i++){
            char c = moves.charAt(i);    
            switch(c) {
                case 'U':
                    v=v+1;
                    break;
                case 'D':
                    v=v-1;
                    break;
                case 'R':
                    h=h+1;
                    break;
                case  'L':
                    h=h-1;
                    break;
            }
        }
        return h==0 && v==0;
    }
}

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 可以使用Java中的排序功能来实现。可以使用Arrays.sort()函数,将列表中的元素按照字母顺序排序,或者使用Collections.sort()函数,将列表中的元素按用户指定的排序规则排序。 ### 回答2: 为了实现LeetCode 2561题(Rearranging Fruits)的要求,需要使用Java编程语言。主要思路是遍历给定的水果数组,同时用一个哈希表来记录每个水果出现的次数。然后根据题目要求,重新排列水果使得相同类型的水果尽可能接近,并且按照出现次数的非递增顺序排序。 具体实现步骤如下: 1. 创建一个HashMap来存储每个水果的出现次数。遍历给定的水果数组,如果该水果已经存在于HashMap中,则将其出现次数加1;否则,将该水果添加到HashMap,并将其出现次数初始化为1。 2. 创建一个ArrayList来存储已经排列好的水果。通过HashMap的entrySet方法获取到每种水果和它的出现次数,然后将这些entry按照出现次数的非递增顺序进行排序。 3. 遍历排序好的entry集合,根据每个水果的出现次数,在ArrayList中连续添加相应数量的水果。 4. 返回排列好的水果数组。 以下是Java代码的示例实现: ```java import java.util.*; class Solution { public String[] rearrange(String[] fruits) { HashMap<String, Integer> fruitCountMap = new HashMap<>(); // 统计每个水果的出现次数 for (String fruit : fruits) { if (fruitCountMap.containsKey(fruit)) { fruitCountMap.put(fruit, fruitCountMap.get(fruit) + 1); } else { fruitCountMap.put(fruit, 1); } } ArrayList<Map.Entry<String, Integer>> sortedEntries = new ArrayList<>(fruitCountMap.entrySet()); // 根据出现次数进行非递增排序 Collections.sort(sortedEntries, new Comparator<Map.Entry<String, Integer>>() { public int compare(Map.Entry<String, Integer> entry1, Map.Entry<String, Integer> entry2) { return entry2.getValue().compareTo(entry1.getValue()); } }); ArrayList<String> rearrangedFruits = new ArrayList<>(); // 根据出现次数连续添加水果 for (Map.Entry<String, Integer> entry : sortedEntries) { String fruit = entry.getKey(); int count = entry.getValue(); for (int i = 0; i < count; i++) { rearrangedFruits.add(fruit); } } return rearrangedFruits.toArray(new String[0]); } } ``` 使用以上代码,可以对给定的水果数组进行重新排列,使得相同类型的水果尽可能接近,并且按照出现次数的非递增顺序进行排序。返回的结果就是排列好的水果数组。 ### 回答3: 题目要求将一个字符串中的水果按照特定规则重新排列。我们可以使用Java来实现这个问题。 首先,我们需要定义一个函数来解决这个问题。 ```java public static String rearrangeFruits(String fruits) { // 将字符串转换为字符数组方便处理 char[] fruitArray = fruits.toCharArray(); // 统计每种水果的数量 int[] fruitCount = new int[26]; for (char fruit : fruitArray) { fruitCount[fruit - 'a']++; } // 创建一个新的字符数组来存储重新排列后的结果 char[] rearrangedFruitArray = new char[fruitArray.length]; // 逐个将水果按照规则放入新数组中 int index = 0; for (int i = 0; i < 26; i++) { while (fruitCount[i] > 0) { rearrangedFruitArray[index++] = (char) ('a' + i); fruitCount[i]--; } } // 将字符数组转换为字符串并返回 return new String(rearrangedFruitArray); } ``` 上述代码中,我们首先将字符串转换为字符数组,并使用一个长度为26的数组来统计每一种水果的数量。然后,我们创建一个新的字符数组来存储重新排列后的结果。 接下来,我们利用双重循环将每一种水果按照规则放入新数组中。最后,我们将字符数组转换为字符串并返回。 例如,如果输入字符串为`"acbba"`,则经过重新排列后,输出结果为`"aabbc"`。 这样,我们就用Java实现了题目要求的功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

James Shangguan

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

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

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

打赏作者

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

抵扣说明:

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

余额充值