增加整数字符串

时间:2015-02-04 22:40:30

标签: javascript

我最近被要求在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];
}

7 个答案:

答案 0 :(得分:3)

  1. 将字符串拆分为子串,这些子串肯定小到可以正常递增。
  2. 递增/递减最后一个块(基于符号)。
  3. 将任何溢出进入下一个块 - 或从下一个块中借用 - 直到完成。
  4. 再次将整数作为字符串加入。

答案 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(后跟:),我们会检查:

  1. 如果它大于'9'+1,我们就会携带并点击初始增量,因此数字应为1,我们随身携带。
  2. 如果它大于'9',我们正在携带,所以数字应为零,我们随身携带。
  3. 否则,我们没有换行,所以要更换数字但不要随身携带。

答案 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号左边没有数字有可能被改变。

&#13;
&#13;
//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;
&#13;
&#13;

答案 6 :(得分:0)

我的策略

  • 将每个数字作为整数放入数组
  • 将右侧增加一个
  • 向后工作
  • 如果在左侧溢出则添加1
  • 用于负数模型作为减法,即-2 + 1是实际的 - (2 - 1)

代码

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('');
}