LeetCode算法学习笔记——递归、回溯和分治

​​​​​​递归与回溯算法归纳(一) - 知乎

递归

在函数中调用自己的方法

一个大问题可以分解为若干个规模较小,与原问题有相同形式的子问题,这些子问题可以用相同的解题思路来解决(自己里面套着自己,方法一样,传参不同),一直到某个临界点后原路返回。

递归算法有两种模型

模型一: 在递去的过程中解决问题

function recursion(大规模){

if (end_condition){ // 明确的递归终止条件

end; // 简单情景

}else{ // 在将问题转换为子问题的每一步,解决该步中剩余部分的问题

solve; // 递去

recursion(小规模); // 递到最深处后,不断地归来

}

}

模型二: 在归来的过程中解决问题

function recursion(大规模){

if (end_condition){ // 明确的递归终止条件

end; // 简单情景

}else{ // 先将问题全部描述展开,再由尽头“返回”依次解决每步中剩余部分的问题

recursion(小规模); // 递去

solve; // 归来

}

}

阶乘的实现

分析:用函数f(n)表示n的阶乘,则f(n-1)表示(n-1)!,则f(n)=n*f(n-1),如此建立起了大问题和小问题之间的联系,用小问题解决大问题。

public static long f(int n){

if(n == 1) // 递归终止条件

return 1; // 简单情景

return n*f(n-1); // 相同重复逻辑,缩小问题的规模

斐波那契数列

public static int fibonacci(int n) {

if (n == 1 || n == 2) { // 递归终止条件

return 1; // 简单情景

}

return fibonacci(n - 1) + fibonacci(n - 2); // 相同重复逻辑,缩小问题的规模

}

杨辉三角的取值

public static int getValue(int x, int y) {

if(y <= x && y >= 0){

if(y == 0 || x == y){ // 递归终止条件

return 1;

}else{

// 递归调用,缩小问题的规模

return getValue(x-1, y-1) + getValue(x-1, y);

}

}

return -1;

}

注:杨辉三角的列数要小于等于行数

代码是从第0行第0列开始计算

将第x行第y列的值得求解分解为两个可以调用该函数的子问题

回文字符串

分析:

判断一个字符串s是否是回文字符串可分为2步:

  1. 字符串s的的第一的字符和最后一个字符是否相等

  2. 去掉首尾的字符串s是否是回文字符串。

public static boolean isPalindromeString_recursive(String s){

int start = 0;

int end = s.length()-1;

if(end > start){ // 递归终止条件:两个指针相向移动,当start超过end时,完成判断

if(s.charAt(start) != s.charAt(end)){

return false;

}else{

// 递归调用,缩小问题的规模

return isPalindromeString_recursive(s.substring(start+1).substring(0, end-1));

}

}

return true;

}

二分查找

分析:

目标是查找target在low和high之间的位置

将问题分解成两个子问题:查找target在low和1/2(low+high)和target在1/2(low+high)和high之间的位置。

public static int binarySearch(int[] array, int low, int high, int target) {

//递归终止条件

if(low <= high){

int mid = (low + high) >> 1;

if(array[mid] == target){

return mid + 1; // 返回目标值的位置,从1开始

}else if(array[mid] > target){

// 由于array[mid]不是目标值,因此再次递归搜索时,可以将其排除

return binarySearch(array, low, mid-1, target);

}else{

// 由于array[mid]不是目标值,因此再次递归搜索时,可以将其排除

return binarySearch(array, mid+1, high, target);

}

}

return -1; //表示没有搜索到

}

回溯法:

试探法,当搜索到某一步时,发现选择达不到目标,就退回一步重新选择,称为回溯法。

递归是一种算法结构,回溯是一种算法思想,通过递归来实现。

1. 求子集

已知一组数(无重复元素),求这组数可以组成的所有子集。

#include

class Solution{

public:

std::vector>subsets(std::vector&nums){

std::vector>result;

std::vector item;

generate(0,nums,item,result);

return result;

}

private:

void generate(int i,std::vector&nums,

std::vector item,std::vector> &result)

{

if (i>=nums.size())

{

return;

}

else{

item.push_back(nums[i]);

result.push_back(item);

generate(i+1,nums,item,result);

item.pop_back();

generate(i+1,nums,item,result);

}

}

};

 剪枝其实就是在递归中进行条件判断

#include

#include"string"

class Solution{

public:

std::vector generateParenthesis(int n){

std::vector result;

generate("",n,n,result);

return result;

}

private:

void generate(std::string item,int left,int right,std::vector & result){

if (left==0&&right==0)

{

result.push_back(item);

return;

}

if (left>0)

{

generate(item+'(',left-1,right,result);

}

if (left

分治:

将规模为N的问题分解为k个规模较小的子问题,这些问题相互独立且与原问题性质相同。求出问题的解后进行合并。

逆序数

已知数组nums,求新数组count,count[i]代表了在nums[i]右侧且比nums[i]小的元素个数

 

你可能感兴趣的:(leetcode,算法,学习)