iOS算法刷题之贪心与分治_分治算法

分治算法,可以认为是一种算法思想,通过将原问题分解成小规模的子问题,然后根据子问题的结果构造出原问题的答案。这里有点类似动态规划,所以说运用分治算法也需要满足一些条件,你的原问题结果应该可以通过合并子问题结果来计算。

贪心算法可以理解为一种特殊的动态规划问题,拥有一些特殊的性质,可以进一步降低动态规划的时间复杂度。

贪心算法

贪心算法比动态规划多了一个性质:贪心选择性质。我们不需要递归地计算出所有选择的具体结果然后比较求最值,而只需要做出那个最有潜力,看起来最优的选择即可。

贪心算法举例:334. 递增的三元子序列

可以使用谈心的方法将空间复杂度降到O(1),从左到右遍历数组,遍历过程中维护两个变量first和second,分别表示递增的三元子序列中的第一个数和第二个数,任何时候都有first < second 初始时,first = nums[0], second = 正无穷。对于 1<=i<n,当遍历到下标i时,令num = nums[i],进行如下操作: 1,如果num > second,则找到了一个递增的三元子序列,返回true 2,否则如果num > first,则将second的值更新为num 3,否则,将first的值更新为num 如果遍历结束时没有找到递增的三元子序列,返回false。 上述做法的贪心思想是:为了找到递增的三元子序列,first\textit{first}first 和 second\textit{second}second 应该尽可能地小,此时找到递增的三元子序列的可能性更大。

class Solution {
func increasingTriplet(_ nums: [Int]) -> Bool {
    let n = nums.count
    if n < 3 {
        return false
    }
    var first = nums[0]
    var second = Int.max
    for i in 1..<n {
        let num = nums[i]
        if num > second {
            return true
        }else if num > first {
            second = num
        }else {
            first = num
        }
    }
    
    return false
}
}

其他经典贪心算法题:55. 跳跃游戏45. 跳跃游戏 II134. 加油站1024. 视频拼接

分治算法

最典型的分治算法就是归并排序了,核心逻辑如下:

void sort(int[] nums, int lo, int hi) {
    int mid = (lo + hi) / 2;
    /****** 分 ******/
    // 对数组的两部分分别排序
    sort(nums, lo, mid);
    sort(nums, mid + 1, hi);
    /****** 治 ******/
    // 合并两个排好序的子数组
    merge(nums, lo, mid, hi);
}

核心思想就是只要我先把数组的左半部分排序,再把右半部分排序,最后把两部分合并,不就是对整个数组排序了么。先分,然后再治。 其他经典分治算法题:241. 为运算表达式设计优先级105. 从前序与中序遍历序列构造二叉树