sisterAn / JavaScript-Algorithms

基础理论+JS框架应用+实践,从0到1构建整个前端算法体系
5.5k stars 633 forks source link

面试真题:删除字符串中出现次数 >= 2 次的相邻字符 #28

Open sisterAn opened 4 years ago

sisterAn commented 4 years ago
输入:"abbbaca"
输出:"ca"
解释:"abbbaca" => "aaca"=>"ca"
thxiami commented 4 years ago

时间复杂度: O(n), n 为字符的个数 空间复杂度: O(n), 栈所用的空间

/**
 * 删除字符串中出现次数 >= 2 次的相邻字符
 * @param {string}s
 */
function removeDuplicate(s) {
  const stack = [] // Space: O(n)
  let top
  let next
  let i = 0
  while (i < s.length) { // Time: O(n)
    top = stack[stack.length - 1]
    next = s[i]
    if (next === top) {
      // 字符串中出现了相邻字符
      // 1. 移除栈顶字符
      // 2. 移动指针, 指向下一个不同的字符
      stack.pop()
      while (s[i] === top) i += 1
    } else {
      stack.push(next)
      i += 1
    }
  }

  return stack.join('')  // Time: O(n)
}
13001920223 commented 4 years ago

在昨天瓶子酱的基础上增加了判断,如果下一个还是相同字符串,继续累加 没有测试用例,有问题欢迎指出

var removeDuplicates = function(s, k) {
  let stock = []
  for (let i = 0; i < s.length; i++) {
    let prev = stock.pop()
      if (!prev || prev[0] !== s[i]) { // 取第一个字符比较
        stock.push(prev)
        stock.push(s[i])
      } else if(prev.length < k - 1 || prev[0] === s[i+1]) { // 如果长度达不到删除数量 或者与下一个字符相同则继续累加
          stock.push(prev+s[i]) // 相同字符拼接在一起
      }
  }
  return stock.join('')
};
sisterAn commented 4 years ago

时间复杂度: O(n), n 为字符的个数 空间复杂度: O(n), 栈所用的空间

/**
 * 删除字符串中出现次数 >= 2 次的相邻字符
 * @param {string}s
 */
function removeDuplicate(s) {
  const stack = [] // Space: O(n)
  let top
  let next
  let i = 0
  while (i < s.length) { // Time: O(n)
    top = stack[stack.length - 1]
    next = s[i]
    if (next === top) {
      // 字符串中出现了相邻字符
      // 1. 移除栈顶字符
      // 2. 移动指针, 指向下一个不同的字符
      stack.pop()
      while (s[i] === top) i += 1
    } else {
      stack.push(next)
      i += 1
    }
  }

  return stack.join('')  // Time: O(n)
}

👍👍👍

zhaojinzhao commented 4 years ago

var arr = 'abbbaca'.split(''); var startIndex = 0; while(startIndex < arr.length) { var endIndex = startIndex; while(arr[endIndex + 1] === arr[startIndex]) { endIndex++; } if (startIndex !== endIndex) { arr.splice(startIndex, endIndex - startIndex + 1); startIndex = Math.max(0, startIndex - 1); } else { startIndex++; } } arr.join('');

HanTianPeng commented 4 years ago

解题思路:保证相同字符串始终作为栈的一个元素进行存储。 时间复杂度:O(n), 空间复杂度O(n)

function removeDuplicateMoreTwo(s) {
    let stack1 = new Stack();
    for(let i=0; i<s.length; i++) {
        let popValue = stack1.pop(),
            iValue = s[i];

        if(popValue === null) {
            stack1.push(iValue);
        }else if(popValue[0] !== iValue) {
            if(popValue.length >= 2) {
                let secondPopValue = stack1.pop();
                if(secondPopValue === iValue){
                    stack1.push(secondPopValue + iValue);
                }else{
                    stack1.push(secondPopValue);
                    stack1.push(iValue);
                }
            }else{
                stack1.push(popValue);
                stack1.push(iValue);
            }
        }else if(popValue[0] === iValue) {
            stack1.push(popValue + iValue);
        }
    }
    return stack1.dataStore.join('');
}
iconWave commented 4 years ago
const removeDuplicates = (str) => {
  if (str.length === 0) return ''
  let newStr = str.slice(0)
  for(let i = 0; i < newStr.length; i++) {
    if(newStr[i] === newStr[i + 1]) {
      newStr = newStr.replace(/(\w)\1+/g, '')
      i === 0 ? (i = i - 1) : (i = i - 2)
    }
  }
  return newStr
}
supershutong commented 4 years ago

这个和letcode 1209有什么区别吗,从瓶子给的示例看,这完全一样啊

haydenull commented 4 years ago

这个和letcode 1209有什么区别吗,从瓶子给的示例看,这完全一样啊

@supershutong

可以比较下输入字符串为 "aaa" 时的结果,本题返回 "" ,之前的那题返回 "a"

qianlongo commented 4 years ago

正则 + 递归

var removeDuplicates = function(s, k = 2) {
  if (s.length < k) {
    return s
  }

  const repeatLenStrRe = new RegExp(`(.)\\1{${ k - 1 },}`, 'g')
  const replaceStr = s.replace(repeatLenStrRe, '')
  // 说明没有需要再匹配的了
  if (replaceStr === s) {
    return replaceStr
  } else {
    return removeDuplicates(replaceStr, k)
  }
};
XW666 commented 3 years ago

const removeDup = (s) => {

let stack = []

for (let i = 0; i < s.length; i++) {
  let prev = stack.pop()
  if (prev !== s[i]) { 
    stack.push(prev)
    stack.push(s[i])
  } else if (prev === s[i + 1]) {
    stack.push(s[i + 1])
  }
}
return stack.join('')

} removeDup('abbbaca')

tomorrowIsNewDay commented 3 years ago

function ans(str) { // 正则+递归 const reg = /(\w)\1+/g if(!reg.test(str)) return str return ans(str.replace(reg, '')) }

JohnApache commented 3 years ago

和 删除 k 位数一样的方案, 使用 带有 count 字段的对象 作为栈节点, 方便 pop的操作,但是不同的是 边界条件的判断, 因为是 ,不知道会重复多少次,所以删除节点放到 push 下一个不同字符的节点前, 一起删除,

还有需要注意的边界条件有两点