常用算法集合

动态规划
给你一个可装载重量为W的背包和N个物品,每个物品有重量和价值两个属性。其中第i个物品的重量为wt[i],价值为val[i],现在让你用这个背包装物品,最多能装的价值是多少?

int knapsack(int W, vector<int>& wt, vector<int>& val){
	//vector全填入0,base case已初始化
	vector<vector<int>> dp(N + 1, vector<int>(N+1, 0));
	
	for(int i = 1; i <= N; i++){
		for(int w = 1; w <= W; w++){
			if(W - wt[w] < 0)
				dp[i][w] = dp[i - 1][w];
			else dp[i][w] = max(dp[i-1][w], dp[i-1][w-wt[i-1]] + val[i-1]);
		}
	}
}

排序数组中的搜索问题,首先想到二分搜索

二分查找

int binary_search(const int arr[], int start, int end, int key){
	int res = -1;
	int mid;
	while(start <= end){
		mid = begin + (end - begin) / 2;
		if(arr[mid] == key){
			res = mid;
			return res;
		}
		else if(arr[mid] < key)
				start = mid + 1;
		else if(arr[mid] > key)
				end = mid - 1;
			
	}
	return res; //单一出口
}

查找第一个大于等于target的索引

 //查找第一个大于等于target的索引
 //如果target存在,就是查找第一个等于target的位置
 //如果不存在,就是第一个大于target的位置
    int binarySearch(vector<int> arr, int target){
        int len = arr.size();
        if(arr[len - 1] < target) //特判
            return -1;
        
        int l = 0, r = len - 1;
        
        while(l < r){
            int m = l + (r - l) / 2;//向下取整
        
            if(arr[m] < target)
                l = m + 1;
            else
                r = m;
                //这里包含了两种情况
        }
		
        退出的时候是r==l
        return l;
    }
};

查找最后一个大于等于target的索引

//查找最后一个大于等于target的索引
 //如果target存在,就是查找最后一个等于target的位置
 //如果不存在,就是第一个大于target的位置
int searchRight(vector<int>& nums, int target){
        int i = 0, j = nums.size() - 1;

        while(i < j){
            int mid = i + (j - i + 1) / 2; //注意这里要+1,即向上取整
            if(nums[mid] == target){
                i = mid;
            }
            else if(nums[mid] > target){
                j = mid - 1;
            }
            else{ //nums[mid] < target
                i = mid + 1;
            }
        }

        
        return i;
    }

在这里插入图片描述

统计一个数字在排序数组中出现的次数

  1. 先找到该数字出现的第一个位置即leftIndex, 再找到出现的最后一个位置即rightIndex,最后长度即为rightIndex - leftIndex + 1;
class Solution {
public:

    int searchLeft(vector<int>& nums, int target){
        int i = 0, j = nums.size() - 1;

        while(i < j){
            int mid = i + (j - i) / 2;
            if(nums[mid] == target){
                j = mid;
            }
            else if(nums[mid] > target){
                j = mid - 1;
            }
            else{ //nums[mid] < target
                i = mid + 1;
            }
        }

        if(nums[i] == target) return i;
        return -1;
    }

    int searchRight(vector<int>& nums, int target){
        int i = 0, j = nums.size() - 1;

        while(i < j){
            int mid = i + (j - i + 1) / 2;
            if(nums[mid] == target){
                i = mid;
            }
            else if(nums[mid] > target){
                j = mid - 1;
            }
            else{ //nums[mid] < target
                i = mid + 1;
            }
        }

        //注意这里直接返回i,因为既然leftIndex存在,则rightIndex也一定存在
        return i;
    }


    int search(vector<int>& nums, int target) {
        if(nums.size() == 0) return 0;

        int leftIndex = searchLeft(nums, target);
        if(leftIndex == -1) return 0;
        
        int rightIndex = searchRight(nums, target);

        return rightIndex - leftIndex + 1;
    }
};

在这里插入图片描述

可以将数组划分为两部分
左子数组:nums[i] = i;
右子数组:nums[i] != i;
缺失的数字等于“右子数组的首位元素”对应的索引。因此用binarySearch查找“右子数组的首位元素”

  1. 初始化:左边界 i = 0i=0 ,右边界 j = len(nums) - 1j=len(nums)−1 ;代表闭区间 [i, j][i,j]
  2. 循环二分
    m = i + (j -i) / 2
    若nums[m] = m,则“右子数组的首位元素”一定是在[m + 1, j]中。则执行i = m + 1
    若nums[m] != m,则“左子数组的末位元素”一定是在[i, m-1]中,则执行 j =m-1;
  3. 返回值,跳出时, i > j,此时变量i和j分别指向“右子数组的首位元素”和“左子数组的末位元素”,此时返回i即可。
class Solution {
public:
    int missingNumber(vector<int>& nums) {
        int i = 0, j = nums.size() - 1;
        
        while(i <= j){
            int mid = (i + j) / 2; //向下取整
			
			//跳出时,i和j分别指向“右子数组的首位元素”和
            //“左子数组的末位元素”
            if(nums[mid] == mid) i = mid + 1;
            else{
                j = mid - 1;
            }
        }
		
		//跳出时, i > j
        return i;
    }
};

二叉树定义

struct TreeNode{
	int val;
	TreeNode* left;
	TreeNode* right;
	TreeNode(int x): val(x), left(NULL), right(NULL){}
};

给定一个字符串,请将字符串里的字符按照出现的频率降序排列,如果频率相同,则按照字符的ASCII码升序排列。

 sort(vec.begin(), vec.end(), [](const pair<char, int> &x, const pair<char, int>& y)->int{
            if(x.second == y.second)
                return x.first < y.first;
            else
                return x.second > y.second;
             });

滑动窗口模板

int left = 0, right = 0;

while (right < s.size()) {
    // 增大窗口
    window.add(s[right]);
    right++;

    while (window needs shrink) {
        // 缩小窗口
        window.remove(s[left]);
        left++;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值