Skip to content

2696. 删除子串后的字符串最小长度

2696. 删除子串后的字符串最小长度

给你一个仅由 大写 英文字符组成的字符串 s 。

你可以对此字符串执行一些操作,在每一步操作中,你可以从 s 中删除 任一个 "AB" 或 "CD" 子字符串。

通过执行操作,删除所有 "AB" 和 "CD" 子串,返回可获得的最终字符串的 最小 可能长度。

注意,删除子串后,重新连接出的字符串可能会产生新的 "AB" 或 "CD" 子串。

示例

示例 1

输入:s = "ABFCACDB"

输出:2

解释:你可以执行下述操作:

  • 从 "ABFCACDB" 中删除子串 "AB",得到 s = "FCACDB" 。
  • 从 "FCACDB" 中删除子串 "CD",得到 s = "FCAB" 。
  • 从 "FCAB" 中删除子串 "AB",得到 s = "FC" 。

最终字符串的长度为 2 。可以证明 2 是可获得的最小长度。

示例 2

输入:s = "ACBBD"

输出:5

解释:无法执行操作,字符串长度不变。

代码

javascript
// 2696. 删除子串后的字符串最小长度
// https://leetcode.cn/problems/minimum-string-length-after-removing-substrings/

// 只去除 AB 或 CD
export function minimumStringLengthAfterRemovingABOrCDSubstrings(str) {
  while(str.indexOf('AB') > -1 || str.indexOf('CD') > -1) {
    str = str.replace('AB', '').replace('CD', '')
  }
  return str.length
}

// 去除 AB / CD / BC 等所有的两个子串
export function minimumStringLengthAfterRemovingSubstrings(str) {
  const strCharCode = str.split('').map(x => x.charCodeAt(0))

  const getSubstringPosition = () => {
    let subIndex = -1
    for(let i = 0, len = strCharCode.length; i < len - 1; i++) {
      if (strCharCode[i + 1] - strCharCode[i] === 1) {
        subIndex = i
        break
      }
    }
    return subIndex
  }
  let getSubstringIndex = getSubstringPosition()
  while(getSubstringIndex > -1) {
    strCharCode.splice(getSubstringIndex, 2)
    getSubstringIndex = getSubstringPosition()
  }
  return strCharCode.length
}

// 去除 AB / CD / BC 等所有的两个子串,栈实现
export function minimumStringLengthAfterRemovingSubstringsStack(str) {
  const strCharCode = str.split('').map(x => x.charCodeAt(0))
  const resList = []
  strCharCode.forEach(item => {
    if (item - resList[resList.length - 1] === 1) {
      resList.pop()
    } else {
      resList.push(item)
    }
  });
  return resList.length
}
typescript
// 2696. 删除子串后的字符串最小长度
// https://leetcode.cn/problems/minimum-string-length-after-removing-substrings/

// 只去除 AB 或 CD
export function minimumStringLengthAfterRemovingABOrCDSubstrings(str: string): number {
  while(str.indexOf('AB') > -1 || str.indexOf('CD') > -1) {
    str = str.replace('AB', '').replace('CD', '')
  }
  return str.length
}

// 去除 AB / CD / BC 等所有的两个子串
export function minimumStringLengthAfterRemovingSubstrings(str: string): number {
  const strCharCode = str.split('').map(x => x.charCodeAt(0))

  const getSubstringPosition = () => {
    let subIndex = -1
    for(let i = 0, len = strCharCode.length; i < len - 1; i++) {
      if (strCharCode[i + 1] - strCharCode[i] === 1) {
        subIndex = i
        break
      }
    }
    return subIndex
  }
  while(getSubstringPosition() > -1) {
    strCharCode.splice(getSubstringPosition(), 2)
  }
  return strCharCode.length
}

// 去除 AB / CD / BC 等所有的两个子串,栈实现
export function minimumStringLengthAfterRemovingSubstringsStack(str: string): number {
  const strCharCode = str.split('').map(x => x.charCodeAt(0))
  const resList: number[] = []
  strCharCode.forEach(item => {
    if (item - resList[resList.length - 1] === 1) {
      resList.pop()
    } else {
      resList.push(item)
    }
  });
  return resList.length
}

测试代码

ts
import { expect, test } from 'vitest'
import {
  minimumStringLengthAfterRemovingABOrCDSubstrings,
  minimumStringLengthAfterRemovingSubstrings,
  minimumStringLengthAfterRemovingSubstringsStack
} from './typescript.js'
import {
  minimumStringLengthAfterRemovingABOrCDSubstrings as minimumStringLengthAfterRemovingABOrCDSubstringsJs,
  minimumStringLengthAfterRemovingSubstrings as minimumStringLengthAfterRemovingSubstringsJs,
  minimumStringLengthAfterRemovingSubstringsStack as minimumStringLengthAfterRemovingSubstringsStackJs
} from './javascript.js'

// 只去除 AB 或 CD
test(`'ABFCACDB' toBe 2`, () => {
  expect(minimumStringLengthAfterRemovingABOrCDSubstrings('ABFCACDB')).toBe(2)
})

test(`'ACBBD' toBe 5`, () => {
  expect(minimumStringLengthAfterRemovingABOrCDSubstrings('ACBBD')).toBe(5)
})

test(`'ABFCJACDBK' toBe 4`, () => {
  expect(minimumStringLengthAfterRemovingABOrCDSubstrings('ABFCJACDBK')).toBe(4)
})

test(`'ABFCACDB' toBe 2`, () => {
  expect(minimumStringLengthAfterRemovingABOrCDSubstringsJs('ABFCACDB')).toBe(2)
})

test(`'ACBBD' toBe 5`, () => {
  expect(minimumStringLengthAfterRemovingABOrCDSubstringsJs('ACBBD')).toBe(5)
})

test(`'ABFCJACDBK' toBe 4`, () => {
  expect(minimumStringLengthAfterRemovingABOrCDSubstringsJs('ABFCJACDBK')).toBe(4)
})

// 去除 AB / CD / BC 等所有的两个子串
test(`'ABFCACDB' toBe 2`, () => {
  expect(minimumStringLengthAfterRemovingSubstrings('ABFCACDB')).toBe(2)
})

test(`'ACBBD' toBe 5`, () => {
  expect(minimumStringLengthAfterRemovingSubstrings('ACBBD')).toBe(5)
})

test(`'ABFCJACDBK' toBe 2`, () => {
  expect(minimumStringLengthAfterRemovingSubstrings('ABFCJACDBK')).toBe(2)
})

test(`'ABFCACDB' toBe 2`, () => {
  expect(minimumStringLengthAfterRemovingSubstringsJs('ABFCACDB')).toBe(2)
})

test(`'ACBBD' toBe 5`, () => {
  expect(minimumStringLengthAfterRemovingSubstringsJs('ACBBD')).toBe(5)
})

test(`'ABFCJACDBK' toBe 2`, () => {
  expect(minimumStringLengthAfterRemovingSubstringsJs('ABFCJACDBK')).toBe(2)
})

// 去除 AB / CD / BC 等所有的两个子串,栈实现
test(`'ABFCACDB' toBe 2`, () => {
  expect(minimumStringLengthAfterRemovingSubstringsStack('ABFCACDB')).toBe(2)
})

test(`'ACBBD' toBe 5`, () => {
  expect(minimumStringLengthAfterRemovingSubstringsStack('ACBBD')).toBe(5)
})

test(`'ABFCJACDBK' toBe 2`, () => {
  expect(minimumStringLengthAfterRemovingSubstringsStack('ABFCJACDBK')).toBe(2)
})

test(`'ABFCACDB' toBe 2`, () => {
  expect(minimumStringLengthAfterRemovingSubstringsStackJs('ABFCACDB')).toBe(2)
})

test(`'ACBBD' toBe 5`, () => {
  expect(minimumStringLengthAfterRemovingSubstringsStackJs('ACBBD')).toBe(5)
})

test(`'ABFCJACDBK' toBe 2`, () => {
  expect(minimumStringLengthAfterRemovingSubstringsStackJs('ABFCJACDBK')).toBe(2)
})