什么是贪心算法
贪心算法是一种常用的算法思想,它是一种在每一步选择中都采取当前状态下最优的选择,从而希望导致全局最优解的算法。
贪心算法通常分为两种类型:
- 基于贪心策略的优化问题:该类问题中,需要对某个目标函数进行最大化或最小化的优化,而目标函数通常可以分解为若干个子问题,且每个子问题的最优解可以直接得到,因此我们可以采取贪心策略,即在每个子问题中都选择当前最优解,最终得到全局最优解。
- 基于贪心思想的组合优化问题:该类问题中,需要从一个集合中选择一部分元素,使得这些元素满足某些条件,并且达到某个优化目标。在这种问题中,我们也可以采取贪心思想,即在每一步中都选择当前最优的元素,最终得到一个可行解或最优解。
贪心算法的优点是简单、高效,容易实现和调试。但是,贪心算法不能保证得到全局最优解,因此在某些情况下可能会得到次优解或不可行解。因此,在使用贪心算法时需要注意问题的特殊性和局限性,确保问题可以适用贪心算法。
- 题目描述
字符串 S 由小写字母组成。我们要把这个字符串划分为尽可能多的⽚段,同⼀字母最多出现在一个片段中。返回一个表示每个字符串片段的⻓度的列表。
例子
输⼊:S = "ababcbacadefegdehijhklij"
输出:[9,7,8]
解释:
划分结果为 "ababcbaca", "defegde", "hijhklij"。 每个字⺟最多出现在⼀一个⽚片段中。
像 "ababcbacadefegde", "hijhklij" 的划分是错误的,因为划分的⽚段数较少。
提示
S的⻓度在[1, 500]之间。 S只包含小写字母'a' 到 'z' 。
- 思考
1 思路很简单,利用递归,不间断的去查找 2 利用贪⼼算法和双指针,⾸先使⽤一个数组存储所有字符出现的最后位置,然后利用双指针,一个指向子串开始的位置,⼀个指向子串结束的位置,然后不断查找,当发现一个字⺟已经到达了它在字符串串中的最后位置的时候,就是相当于发现了一个符合条件的⼦串。
代码很简单,稍微看下,就明白了
这⾥可以得到⼀个小提示,⼀旦涉及到字符串的时候,很⾃然的就要想到使⽤一个⻓度为26的数组来存储。
- 实现
/**
* @param {string} S * @return {number[]} */
const getBigStr = (S, begin, res) => {
let max = begin;
const len = S.length;
if (begin >= S.length) {
return;
}
const lastIndex = S.lastIndexOf(S[begin]);
if (lastIndex !== -1) {
max = Math.max(max, lastIndex);
let s1 = S.substring(begin, lastIndex + 1);
for (let i = 1; i < s1.length; i++) {
const newLastIndex = S.lastIndexOf(s1[i]);
if (newLastIndex > max) {
max = newLastIndex;
s1 = S.substring(begin, max + 1);
}
}
res.push(S.substring(begin, max + 1));
} else {
res.push(S[begin]);
max = begin++;
}
return max;
};
export default (S) => {
let res = [];
let max = -1;
while (max < S.length) {
max = getBigStr(S, max + 1, res);
}
return res.map((item) => item.length);
};
export default (S) => {
if (S == null || S.length === 0) {
return null;
}
const list = [];
// 记录每个字符出现在字符串串中的最后的位置 const map = new Array(26).fill(0);
for (leti = 0; i < S.length; i++) {
map[S.charCodeAt(i) - 97] = i;
}
// 记录每个⼦子串串出现的开始和结束 let last = 0;
let start = 0;
for (leti = 0; i < S.length; i++) {
last = Math.max(last, map[S.charCodeAt(i) - 97]);
if (last === i) {
list.push(last - start + 1);
start = last + 1;
}
}
return list;
};
时间复杂度O(n), 空间复杂度O(1)