我最近被要求在Javascript中增加一个整数字符串作为面试的一部分。我设法做到了,但我的代码非常混乱。在Javascript(或任何语言)中将整数字符串递增1的好算法是什么?
"1"=>"2"
"9"=>"10"
"-10"=>"-9"
"-1"=>"0"
"123456"=>"123457"
这是为了防止整数溢出,所以很明显我无法将字符串转换为整数。
无论谁提出解决方案,请使用以下代码进行测试(假设您的函数名为inc
):
var s = '-1000';
for(var i = -999; i <= 999; i++) {
s = inc(s);
if(s !== i.toString())
throw [s, i];
}
答案 0 :(得分:3)
答案 1 :(得分:3)
由于您特别要求不将字符串转换为整数,因此这里只使用字符串操作函数 - 没有parseInt
。
要使用它,只需致电incrementString('123')
。
var incrementMapPositive = { '0': '1', '1': '2', '2': '3', '3': '4', '4': '5', '5': '6', '6': '7', '7': '8', '8': '9', '9': '0' };
var incrementMapNegative = { '0': '9', '9': '8', '8': '7', '7': '6', '6': '5', '5': '4', '4': '3', '3': '2', '2': '1', '1': '0' };
function incrementString(str, pos) {
if (!str)
return '';
// handle case '-0'
if (/^-0+$/.test(str))
str = '0';
// position count starts from the end, so get the proper index
var posFromStart = str.length - 1 - (pos || 0);
// get the character to increment (use the last one if none specified)
var chr = str.charAt(posFromStart);
var isNegative = str.charAt(0) === '-';
var incrementMap = isNegative ? incrementMapNegative : incrementMapPositive;
// if the very first digit is carried (e.g. incrementing from 99 to 100), we need to add a '1'
var newChr = !chr ? '1' : incrementMap[chr];
// build the new string with the replaced digit
var incremented = str.substr(0, posFromStart) + newChr + str.substr(posFromStart + 1);
// detect if we need to carry/borrow from the next digit
if (!isNegative && newChr === '0' || isNegative && newChr === '9')
incremented = incrementString(incremented, (pos || 0) + 1);
//clean leading zeros
incremented = incremented.replace(/^(-)?0+/, '$1');
if (incremented === '-')
incremented = '0';
return incremented;
}
编辑:用映射对象替换if-else块。现在也正确地增加负数。
编辑2:进行了一些清理并添加了一些内联注释以更好地解释代码。
编辑3:处理案例'-0'
答案 2 :(得分:1)
为了正确处理,您可以使用以下内容:
function replaceChar(str, index, character) {
return str.substr(0, index) + character + str.substr(index + character.length);
}
function incStr(str) {
var carry = false;
var ret = str;
for (var i = str.length; i > 0; --i) {
var inc = str.charCodeAt(i - 1);
if (i === str.length) {
++inc;
}
if (carry) {
++inc;
}
if (inc > 58) {
carry = true;
ret = replaceChar(ret, i - 1, "1");
} else if (inc === 58) {
carry = true;
ret = replaceChar(ret, i - 1, "0");
} else {
carry = false;
ret = replaceChar(ret, i - 1, String.fromCharCode(inc));
}
};
if (carry) {
return "1" + ret;
} else {
return ret;
}
}
var testData = ["13", "14", "19", "20", "300", "08974871238471923501", "999999999999999999999999999"];
var results = testData.map(function(it) {
return incStr(it);
});
document.getElementById("results").textContent = JSON.stringify(results);
<pre id="results"></pre>
它绝对不是最漂亮的实现,因为它在此过程中会创建大量字符串(输入中每个数字至少有一个字符串),但它将以线性速度运行(取决于输入长度)并且不会气球在记忆中为大值。
没有一个实际的字符串到数字转换,因为我们知道十个有效数字([0-9]
)按顺序排列,我们可以简单地增加字符代码。如果超出9
(后跟:
),我们会检查:
'9'+1
,我们就会携带并点击初始增量,因此数字应为1,我们随身携带。'9'
,我们正在携带,所以数字应为零,我们随身携带。答案 3 :(得分:1)
此代码适用于正数和负数 - 不是简单的,而是自我解释的。祝你好运......
var tests = ['9007199254740992','999999999999999999','-999999999','-0','-80','800','99']
function addOne(num){
if (Math.abs(parseInt(num,10)) == 0){return '1'};
var numArray = num.split(''),
answer = [];
var sign = 1;
if (numArray[0] == '+' || numArray[0] == '-'){
if (numArray[0] == '-'){sign = -1};
numArray.splice(0,1);
}
var idx = numArray.length;
var next_int = 0;
var carry = 1; /* first add 1 */
while(idx-- && carry != 0){
next_int = parseInt(numArray[idx],10) + (sign * carry);
if (sign > 0){
answer[idx] = (next_int >= 10 ? next_int - 10 : next_int)
carry = (next_int >= 10 ? 1 : 0)
} else {
answer[idx] = (next_int == -1 ? 9 : Math.abs(next_int));
carry = (next_int == -1 ? 1 : 0)
}
if (carry == 0){
while(idx--){
answer[idx] = numArray[idx]
}
}
}
if (sign > 0){
return (carry == 0 ? answer.join('') : carry + answer.join(''));
} else {
return ('-' + answer.join(''));
}
}
for (var i = 0;i<tests.length;i++){
console.log (' Num In: ' + tests[i] + ' Num Out: ' + addOne(tests[i]));
}
Num In:9007199254740992 Num Out:9007199254740993
Num In:999999999999999999 Num Out:1000000000000000000 / *大于* *
Num In:-999999999 Num Out:-999999998
Num In:-0 Num Out:1
Num In:-80 Num Out:-79
Num In:800 Num Out:801
Num In:99 Num Out:100
答案 4 :(得分:0)
我的方法可能是使用数组方法的内存密集型方法:
var num = '12345';
var newNum = num.split('').map(function(el){
return ''+(++el);
}).join('');
修改强>
忘了考虑随身携带 - 请刻好^^
var num = '278889';
var newNum;
var temp = num.split('').reverse().reduce(function(carry, el){
// carry[0] holds the carry from last operation, carry[1] is our new num
// ~~num is same as Math.float() or in this case paseInt
++el;
el += carry[0];
return [ ~~(el / 10), (el % 10) + '' + carry[1] ];
}, [0,'']);
// We have to check if last carry was zero or not
newNum = (temp[0] != 0 ? temp[0] : '') + temp[1];
// outputs ["390000"]
console.log([newNum]);
答案 5 :(得分:0)
让我们在添加到。时查看最后一个具有JavaScript精度的值。
var s = ""+Number.MAX_SAFE_INTEGER;
并添加一个。
s++;//"9007199254740992"
现在下一个增量将无法增加价值。为了增加,需要进行一些调整。好处是递增1允许进行一些基本假设。基本上9号左边没有数字有可能被改变。
//defined
function inc(num,i){
i = i == undefined ? 1 : i;
var c = num[num.length-i];
var left = num.substr(0,num.length-i);
var right = num.substr(num.length-i+1);
if( c == 9 ){
return inc(left+0+right,i+1);
}else{
return left+(+c+1)+right;
}
}
//used
var s = ""+(Number.MAX_SAFE_INTEGER+1);//"9007199254740992"
for(var i = 0; i < 10; i++){
s = inc(s);
}
alert(s);//"9007199254741002"
&#13;
答案 6 :(得分:0)
我的策略
代码
function inc(str) {
var parts = [];
var i = 0;
var negative = str[0] === '-';
for (i = negative ? 1 : 0; i < str.length; i++) {
parts.push(str.charCodeAt(i) - 48);
}
parts[parts.length - 1] += (negative ? -1 : 1);
for (i = parts.length - 1; i >= 0; i--) { // carry right to left
if (parts[i] > 9) { // overflow
parts[i] = 0;
if (i > 0) {
parts[i - 1]++;
} else {
parts.unshift(1); // 99 -> 100 case
}
} else if (parts[i] < 0) { // underflow
parts[i] = 9;
if (i > 0) {
parts[i - 1]--;
} else {
parts.shift(); // 100 -> 99 case
}
}
}
if (negative) {
parts.unshift("-");
}
return parts.join('');
}