我正在解决以下问题:
加里(Gary)是一个狂热的徒步旅行者。他精心跟踪自己的远足,并密切关注地形等小细节。在他的最后一次远足中,他走了正好n步。
对于他迈出的每一步,他都指出这是上坡U步还是下坡D步。加里(Gary)的远足在海平面开始和结束,每次上或下的步数都代表着海拔高度每变化1单位。我们定义以下术语:
一座山是一系列从海平面上升的连续步骤,从从海平面上升到从海平面下降到结束。
山谷是指一系列从海平面以下的连续台阶,从海平面向下的台阶开始,直至海平面的上升。 考虑到加里上次徒步旅行时上下的顺序,找到并打印出他走过的山谷数。
例如,如果加里的路径为s = [DDUUUUDD],则他首先进入2个单位深度的山谷。然后,他爬上了2个单元高的山。最后,他回到海平面并结束了远足。
功能说明
在下面的编辑器中完成countingValleys函数。它必须返回一个整数,该整数表示加里所遍历的谷数。
countingValleys具有以下参数:
n:Gary采取的步骤数
s:描述他的路径的字符串 输入格式
第一行包含一个整数,即Gary远足的步数。 第二行包含一个字符串,其中包含描述其路径的字符。
输出格式
打印一个整数,表示加里(Gary)远足时经过的山谷数。
样本输入
8 乌迪都(UDDDUDUU)
样本输出
1
以下是我在Java中的实现。它适用于小型测试用例,但不适用于大型测试用例。
static int countingValleys(int n, String s) {
//Use a hashmap to keep track of the number of moves.
HashMap<Character,Integer> map = new HashMap();
boolean sea = true;//check if we are at sea level
//if both D and U have the same total no, we are at sea level.
map.put('D',0);
map.put('U',0);
int valleys = 0;//count num of valleys
for(int i = 0; i < n; i++){
char key = s.charAt(i);
//check if we are at sea level
if(map.get('D') == map.get('U')){//<--PROBLEM
sea = true;
}
else
sea = false;
if(sea == true && key == 'D'){//if we are at sea level and our next key is D, we have a valley
valleys += 1;
}
map.put(key,map.get(key) + 1);//add move and update our hashmap
}
return valleys;
}
问题似乎出在“ if(map.get('D')== map.get('U'))”,对于大数字似乎返回false,有人可以告诉我为什么吗?如果我将每个map.get()分配给一个变量并比较这些变量,则可以使用它。
我还使用“ new Object()”类型在javascript中编写了完全相同的东西,它通过了所有测试用例,但是在带有hashmap的Java中不起作用,为什么?
答案 0 :(得分:4)
首先,如其他答案所述,在这种情况下,使用.equals()
代替==
。更好的方法是,您甚至不需要使用Map
。一个整数就足够了。
您的问题是...returning false for big numbers, can someone tell me why?
这是原因。
您需要了解几件事
首先,您需要知道Java中有两种类型的变量:基本变量和参考变量。
整数通常是基元,因此变量本身就是整数值:int a = 1234;
:a
本身具有值1234。
要比较原始变量,您应该使用==
对于引用类型,变量本身是“指针”。在Java中,有用于原语的包装器类。例如,Integer
是int
的包装。因此,在Integer a = new Integer(1234);
中,a
不包含值1234
。它是指向Integer
对象引用的指针。在引用类型变量上使用==
不会比较内容,而只是检查指针值是否相同(即检查它们是否指向相同的对象实例)
从Java 1.5(iirc)开始,有一个称为自动装箱(和拆箱)的功能,该功能使程序员可以在原始类型及其对应的包装器之间进行转换。
过去,您需要执行以下操作:
int a = 1234;
Integer intWrapper = new Integer(a);
int b = intWrapper.intValue();
使用自动装箱,您只需要编写:
int a = 1234;
Integer intWrapper = a;
int b = intWrapper;
然后编译器会将其转换为:
int a = 1234;
Integer intWrapper = Integer.valueOf(a);
int b = intWrapper.intValue();
到目前为止一切还好吗?
所以您的代码使用少量数字的原因是:
Integer.valueOf()
正在缓存经常使用的值。来自API文档:
public static Integer valueOf(int i)
返回一个表示指定int值的Integer实例。如果不需要新的Integer实例,则通常应优先于构造方法Integer(int)使用此方法,因为此方法通过缓存经常请求的值可能会产生明显更好的空间和时间性能。 此方法将始终缓存-128至127(包括)范围内的值,并且可能会缓存该范围之外的其他值。
由于它正在缓存包装器,因此,如果要执行map.put(key,map.get(key) + 1)
,则转换为get(key) + 1
时,如果int
的结果是Integer
,则返回Integer
一个较小的数字,将是具有相同int
值的==
的相同实例。这意味着Integer
仍然有效(因为变量指向相同的==
)。但是,如果它是一个未缓存的数字,则每次调用将是一个不同的实例,并且Integer
将不起作用(因为变量指向Integer
的不同实例,尽管{{1 }}实例相同)
关于算法的建议,尽管有一些话题:
您的逻辑过于复杂。可以大大简化为(伪代码):
countValley(String s) {
currentLevel = 0
valleyCount = 0
for (step in s) {
if step == 'U' {
++currentLevel;
if (currentLevel == 0) { // returning to sea level
++valleyCount
}
} else if step == 'D' {
--currentLevel;
}
}
return valleyCount
}
答案 1 :(得分:0)
首先,不要使用'=='。对所有类使用.equals扩展Object。
答案 2 :(得分:0)
要比较包装器类(整数,浮点数,长整型,双精度型)的内容,请使用.equals()。 “ ==”将比较两个对象的引用。即使两个引用包含相同的内容,它们也可能不同。但是,在比较 value 类型(例如int,float,long,double)时,可以使用“ ==”。
答案 3 :(得分:0)
比较包装器类需要使用.equals。 可以使用Objects.equals:
java.util.Objects.equals(firstInteger, secondInteger);
对于上述情况:
if(java.util.Objects.equals(map.get('D'), map.get('U'))){
sea = true;
}
答案 4 :(得分:0)
解决方案2:使用数组而不是HashMap。构建之后,找到D序列,依此类推。