面试高频算法 2023.3.07复习

1 数组求和问题,2 sum, 3 sum, 3-Sum Closest

2 Sum

Find a pair of two elements in an array, whose sum is a given target number. Assume only one qualified pair of numbers existed in the array, return the index of these numbers (e.g. returns (i, j), smaller index in the front).

用hash_map:

vector<int> addsToTarget(vector<int>& numbers, int target) {
	unordered_map<int, int> mp;
	vector<int> res(2);
	for (auto it = numbers.begin(); it != numbers.end(); ++it) {
		if (mp.count(*it)) {
			res[0] = it - numbers.begin() + 1;//
			res[1] = mp[*it] + 1;
			return res;
		}
		else
			mp[target - *it] = it - numbers.begin();
	}
}


用排序

bool hasArrayTwoCandidates(int a[], int arr_size, int sum) {
	int l, r;
	sort(a, a + arr_size );
	l = 0;
	r = arr_size - 1;
	while (l < r) {
		if (a[l] + a[r] == sum) {
			return true;
		}
		else if (a[l] + a[r] < sum) {
			++l;
		}
		else {
			--r;
		}
	}
	return false;

}
3 Sum

Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero. Example For example, given array S = {-1 0 1 2 -1 -4}, A solution set is: (-1, 0, 1) (-1, -1, 2) Note Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ≤ b ≤ c)

用hash_map:

bool three_sum(int nums[], int n, int target) {
	unordered_map<int, int> arr_hash;
	for (int i = 0; i < n; ++i)
		arr_hash[nums[i]] = i;

	for (int i = 0; i < n; ++i) {
		for (int j = i + 1; j < n; ++j) {
			if(arr_hash.find(target - nums[i] - nums[j])!=arr_hash.end())
				//确保找到的点在j之后,也就是没有使用过
				if (arr_hash[target - nums[i] - nums[j]] > j) {
					return 1;
				}
		}
	}
	return 0;
}

用排序

set<vector<int>> find_triplets(vector<int> arr,int target) {
	sort(arr.begin(), arr.end());
	set<vector<int>> triplets;
	vector<int> triplet(3);
	int n = arr.size();

	for (int i = 0; i < n; ++i) {
		int l = i + 1, r = n - 1;
		while (l < r) {
			if (arr[l] + arr[r] == target - arr[i]) {
				triplet[0] = i, triplet[1] = l, triplet[2] = r;
				triplets.insert(triplet);
				++l;
			}
			else if (arr[l] + arr[r] < target - arr[i]) {
				++l;
			}
			else {
				--r;
			}
		}
	}
	return triplets;
}
3 Sum closest

Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target.

Return the sum of the three integers. You may assume that each input would have exactly one solution.

For example, given array S = {-1 2 1 -4}, and target = 1. The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).

int threeSumclosest(vector<int>& num, int target) {
	if (num.size() <= 3)
		return accumulate(num.begin(), num.end(), 0);
	sort(num.begin(), num.end());

	int res = num[0] + num[1] + num[2];
	for (int i = 0; i < num.size() - 2; ++i) {
		int j = i + 1; 
		int k = num.size() - 1;

		while (j<k) {
			int tmp = num[i] + num[j] + num[k];
			if (abs(res - target) > abs(tmp - target))
				res = tmp;
			if (res == target)
				return res;
			(tmp > target) ? --k : ++j;
		}
		
	}
	return res;
}

2 ⼦数组问题系列 Subarray Max Sum

Subarray max sum 最大子数组和

给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
Find the contiguous subarray within an array (containing at least one number) which has the largest sum.

For example, given the array [−2,1,−3,4,−1,2,1,−5,4], the contiguous subarray [4,−1,2,1] has the largest sum = 6.

/*
         做一个简单的dp,维护当前这个index的最大连续子数组和
*/

     vector<int> dp(nums.size());
     dp[0]=nums[0];

     for(int i=1;i<nums.size();++i){
         
         dp[i]=max(dp[i-1]+nums[i],nums[i]);
     }
     int ans=INT_MIN;
     for(auto i:dp)
         ans=max(ans,i);
     
     return ans;
Subarray Sum is zero(k)

Given an integer array, find a subarray where the sum of numbers is zero. Your code should return the index of the first number and the index of the last number.

Example Given [-3, 1, 2, -3, 4], return [0, 2] or [1, 3].

Note There is at least one subarray that it’s sum equals to zero.

要求复杂度O(n)

vector<int> subarraySum(vector<int> nums) {
	vector<int> res;
	unordered_map<int, int> hash;
	hash[0] = 0;


	int sum = 0;
	for (int i = 0; i < nums.size(); ++i) {
		sum += nums[i];
		if (hash.find(sum) != hash.end()) {
			res.push_back(hash[sum]);
			res.push_back(i);
		}
		else {
			hash[sum] = i + 1;
		}
	}
	return res;

}

the sum of numbers is k.

vector<int> subarraySum(vector<int> nums,int k) {
	vector<int> res;
	unordered_map<int, int> hash;
	hash[0] = 0;


	int sum = 0;
	for (int i = 0; i < nums.size(); ++i) {
		sum += nums[i];
		if (hash.find(sum - k) != hash.end()) {
			res.push_back(hash[sum - k]);
			res.push_back(i);
		}
		else {
			hash[sum] = i + 1;
		}
	}
	return res;

}
Subarray Sum Closest 0

Given an integer array, find a subarray with sum closest to zero. Return the indexes of the first number and last number.

Example Given [-3, 1, 1, -3, 5], return [0, 2], [1, 3], [1, 1], [2, 2] or [0, 4]

Challenge O(nlogn) time

//mp.first保存字符串前缀和,mp.second保留对应index
//对前缀和进行排序
//找到相邻两项绝对插值最小的点,即为所求
//左端点就是index,右端点是index-1
vector<int> subarraySumclosest(vector<int> nums) {
	vector<int> res;

	const int n = nums.size();
	vector<pair<int, int>> sum_preindex(n+1);
	int sum = 0;
	for (int i = 0; i <= n; ++i) {
		sum_preindex[i].first = sum;
		sum_preindex[i].second = i;
		if(i<n)
		sum += nums[i];
	}

	sort(sum_preindex.begin(), sum_preindex.end());

	int min_diff = INT_MAX;
	for (int i = 1; i <= n; ++i) {
		int sum_diff = abs(sum_preindex[i].first - sum_preindex[i - 1].first);
		if (sum_diff < min_diff) {
			min_diff = sum_diff;
		}
	}

	vector<int> index;
	for (int i = 1; i <= n; ++i) {
		int sum_diff = abs(sum_preindex[i].first - sum_preindex[i - 1].first);
		if (sum_diff == min_diff) {
			int left_index = min(sum_preindex[i - 1].second, sum_preindex[i].second);
			int right_index=max(sum_preindex[i - 1].second, sum_preindex[i].second)-1;
			res.push_back(left_index);
			res.push_back(right_index);
		}
		
	}
	return res;

}
Maximum Product Subarray乘积最大子数组

给你一个整数数组 nums ,请你找出数组中乘积最大的非空连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。

Find the contiguous subarray within an array (containing at least one number) which has the largest product.
For example, given the array [2,3,-2,4], the contiguous subarray [2,3] has the largest product = 6.
maxDP[i + 1] = max(maxDP[i] * A[i + 1], A[i + 1], minDP[i] * A[i + 1])
minDP[i + 1] = min(minDP[i] * A[i + 1], A[i + 1], maxDP[i] * A[i + 1]
dp[i + 1] = max(dp[i], maxDP[i + 1])

注意:最小负数*负数 可能= 最大值

//dpmax[i]保存以i+1为终点区间的累乘最大值
//dpmin[i]保存以i+1为终点区间的累乘最小值
int maxProduct(int A[], int n) {
	if (n == 0)return 0;
	int maxdp[10000];
	memset(maxdp, INT_MIN, sizeof(maxdp));
	int mindp[10000];
	memset(mindp, INT_MAX, sizeof(mindp));
	maxdp[0] = A[0], mindp[0] = A[0];

	for (int i = 0; i < n-1; ++i) {
		//A[i]时是以i+1为终点的累乘最大值
		maxdp[i + 1] = max({ maxdp[i] * A[i + 1],A[i + 1],mindp[i] * A[i + 1] });
		//maxdp[i]是可以不取i+1节点,即前i+1个节点中任选任意个的节点最大值
		//maxdp[i + 1] = max({ maxdp[i] * A[i + 1],maxdp[i],mindp[i] * A[i + 1] });
		mindp[i+1] = min({ mindp[i] * A[i+1],A[i + 1],maxdp[i] * A[i+1] });
	}
	
	int ans = INT_MIN;
	for (int i = 0; i < n; ++i) {
		ans = max(ans, maxdp[i]);
	}
	return ans;
}

3 买卖股票 Best Time to Buy and Sale Stock

Best Time to Buy and Sell Stock

Say you have an array for which the ith element is the price of a given stock on day i.

If you were only permitted to complete at most one transaction (ie, buy one and sell one share of the stock), design an algorithm to find the maximum profit.

思路:找到一个最大的值,一个最小的值(要求在最大的值之前),两者作差。 == 维护更新最小的值,用当前节点一直减去最小的值,其中,最大的值减去最小的值的情况肯定在里面,且复杂度为O(n)

int maxProfit(const vector<int>& price) {
	int minp = price[0];
	int profit = 0;
	for (int i = 1; i < price.size(); ++i) {
		profit = max(profit, price[i] - minp);
		minp = min(minp, price[i]);
	}
	return profit;
}
Best Time to Buy and Sell Stock II

Say you have an array for which the ith element is the price of a given stock on day i.

Design an algorithm to find the maximum profit. You may complete as many transactions as you like (ie, buy one and sell one share of the stock multiple times). However, you may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).

可以买入卖出无数次,可以分解为子问题(今天可赚最大值=昨天可以赚的最大值+今天能赚的),用贪心的思想:

int maxprofit11(vector<int>& prices) {
	int len = prices.size();
	int dp[1000];
	memset(dp, 0, sizeof(dp));
	for (int i = 1; i < len; ++i) {
		dp[i] = max(dp[i - 1] + prices[i] - prices[i - 1], dp[i-1]);
	}
	for (int i = 0; i < prices.size(); ++i)
		cout << dp[i] << " ";
	cout << endl;
	return dp[len-1];
}
Best Time to Buy and Sell Stock III

Say you have an array for which the ith element is the price of a given stock on day i.
Design an algorithm to find the maximum profit. You may complete at most two transactions.
Note: You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).

如果当前节点的解,既依赖于前驱问题的解,又依赖于后驱问题的解,但这两部分又互相独⽴,则可以分别⾃左开始DP,计算从最左节点到当前节点的结果;⾃右开始DP,计算从最右节点到当前节点的结果;再⽤同⼀个DP Table来合并解。

从前往后做一次dp,记录到0~ i天,买卖一次可赚的最大值

从后往前做一次dp,记录从第i天~最后一天,买卖一次赚的最大值

最后将两个dp相加求和,取最大值即可。

int maxprofit1(vector<int>& prices) {
	int dp_o[1000];
	int dp_r[1000];
	memset(dp_o, 0, sizeof(dp_o));
	memset(dp_r, 0, sizeof(dp_r));
	int min1 = prices[0];
	int len = prices.size();
	for (int i = 1; i < prices.size(); ++i) {
        //只允许买卖一次,和上面买卖多次的差别是:没有加上dp[i-1]的结果
        //只允许买卖一次,就是要么今天不买卖,要么今天买卖
        //今天买卖的话,用今天的价格减去前面天的最低价
		dp_o[i] = max(dp_o[i - 1], prices[i] - min1);
		min1 = min(prices[i], min1);
	}
	for (int i = 0; i < prices.size(); ++i)
		cout << dp_o[i] << " ";
	cout << endl;
	int max1 = prices[len - 1];
	for (int i = len - 2; i >= 0; --i) {
		dp_r[i] = max(max1-prices[i], dp_r[i + 1]);
		max1 = max(max1, prices[i]);
	}
	for (int i = 0; i < prices.size(); ++i)
		cout << dp_r[i] << " ";
	cout << endl;
	int ans = 0;
	for (int i = 0; i < len; ++i) {
		ans = max(ans, dp_r[i] + dp_o[i]);
	}
	return ans;
}

4 寻找丢失数 Single Number

Find Missing Num 丢失的数字

给定一个包含 [0, n] 中 n 个数的数组 nums ,找出 [0, n] 这个范围内没有出现在数组中的那个数

Given an unsorted integer array, find the first missing positive integer.

Example Given [1,2,0] return 3, and [3,4,-1,1] return 2.

Challenge Your algorithm should run in O(n) time and uses constant space.

法一:可以用hashtable记录

法二:桶排序

int firstMissingPostive(vector<int> A){
	const int len = A.size();

	for(int i=0;i<len;++i){
		//当该位置不是正确的数时,将该位置的错误的数放到正确的位置上,一直到合适为止
		while (A[i] > 0 && A[i] <= len && (A[i] != i + 1) && (A[i] != A[A[i] - 1])) {
			//swap
			int temp = A[A[i] - 1];
			A[A[i] - 1] = A[i];
			A[i] = temp;
		}
	}
	for (int i = 0; i < len; ++i) {
		if (A[i] != i + 1)return i + 1;
	}
	return len + 1;
}
Single Num 只出现一次的数字

给你一个 非空 整数数组 nums ,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

Given an array of integers, every element appears twice except for one. Please write a function to find that single one.

建立一个hashtable,key是元素,value是出现的次数,扫描整个数组

void singlenum(vector<int> vec) {
	unordered_map<int,int> mp;
	for (int i = 0; i < vec.size(); ++i) {
		mp[vec[i]] += 1;
	}

	for (auto it = mp.begin(); it != mp.end(); ++it) {
		if (it->second == 1)
			cout << it->first << endl;
	}
}

本题可以用异或,两个相同的数异或为0

int singlenum1(vector<int> vec) {
	int value =0;//初始值为0(相同的数异或就是0啊)
	for (int i = 0; i < vec.size(); ++i) {
		value ^= vec[i];
	}
	return value ;
}
Single Number II 只出现一次的数字 II

给你一个整数数组 nums ,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次 。请你找出并返回那个只出现了一次的元素。

Given 3*n + 1 numbers, every numbers occurs triple times except one, find it. Example Given [1,1,2,3,3,3,2,2,4,1] return 4 Challenge One-pass, constant exstra space

//处理落单的数之外,每个数的bit都是3的倍数,只要对位上做算术求和,然后%3,每个位上就都是落单的数了
int singleNumberII(vector<int> vec) {
	int result = 0, bit_i_sum = 0;
	for (int i = 0; i < 8 * sizeof(int); ++i) {
		bit_i_sum = 0;
		for (int j = 0; j < vec.size(); ++j) {
			//确定每个元素的第i为是否为1,然后将其累加
			bit_i_sum += (vec[j] >> i & 1);
		}
		result |= ((bit_i_sum % 3) << i);
	}
	return result;
}

5 找主元素 Majority Number

Majority Number 多数元素

给定一个大小为 n 的数组 nums ,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。

Given an array of integers, the majority number is the number that occurs more than half of the size of the array. Find it.

Example Given [1, 2, 1, 3, 1, 2, 1], return 1

法一:hashtable,key记录这个值,value记录次数,然后进行一次遍历

法二:遇到两个不同的值就同时删除这两个,直到最后剩下的那个数

int majorityNumber(vector<int> nums) {
	int candicate, cnt=0;
	for (int i = 0; i < nums.size(); ++i) {
		if (cnt == 0) {
			candicate = nums[i];
			cnt++;
		}
		else {
			if (candicate == nums[i]) 
				cnt++;
			else
				cnt--;//遇到两个不同的值就同时删除这两个
		}
	}
	return candicate;
}
Majority Number III 多数元素 III

Given an array of integers and a number k, the majority number is the number that occurs more than 1/k of the size of the array.
Find it.
Example
Given [3,1,2,3,2,3,3,4,4,4] and k=3, return 3.

思路和上一个一样

int majorityNumber(vector<int> nums) {
	int candicate1, candicate2, cnt1, cnt2;
	cnt1 = 0, cnt2 = 0;
	for (int i = 0; i < nums.size(); ++i) {
		if (cnt1 == 0)
			candicate1 = nums[i], cnt1++;
		else if (cnt2 == 0)
			candicate2 = nums[i], cnt2++;
		else if (candicate1 == nums[i])
			cnt1++;
		else if (candicate2 == nums[i])
			cnt2++;
		else
			cnt1--, cnt2--;
	}
	//运行到最后,candacate一定保存了ans和一个干扰项,如果最后一个是决定谁是干扰项和答案的 6,7,1,2,1,这时,cnt1,2=0
	cnt1 = 0, cnt2 = 0;
	for (int i = 0; i < nums.size(); ++i) {
		if (nums[i] == candicate1)
			cnt1++;
		if (nums[i] == candicate2)
			cnt2++;
	}
	return cnt1 > cnt2 ? candicate1 : candicate2;
}

6 排序切分问题,quick sort

Partition Array 给定元素k左边放比k小的,右边放比k大的

Given an array “a” of integers and an int “k”, Partition the array (i.e move the elements in “a”) such that - All elements < k are moved to the left - All elements >= k are moved to the right Return the partitioning Index, i.e the first index “i” a[i] >= k.

quick sort

int partition(vector<int> vec, int pivot) {
	const int n = vec.size();
	int i = 0, j = n - 1;
	while (i < j) {
		while (vec[i] < pivot)
			++i;
		while (vec[j] > pivot)
			--j;
		if (i < j) {
			swap(vec[i], vec[j]);
			++i, --j;
		}
	}
	return i;
}

快排一般用下面这种

int partition(vector<int> vec, int pivot) {
	const int n = vec.size();
	int i = 0, j = n - 1;
	while (i < j) {
		if (vec[i] >= pivot) {
			swap(vec[i], vec[j]);
			--j;//把不符合条件的值放到右边,右边挪动1,左边不动
		}
		else
			++i;
		if (vec[j] <= pivot) {
			swap(vec[i], vec[j]);
			++i;
		}
		else
			--j;
	}
	return i;
}

7 TOP K问题,最⼤堆和最⼩堆

Select K Smallest 找第k大的元素

Get the k smallest elements in an array with O(n) expected time.they don’t need to be sorted.

思路一:先排序,取第k个(不是O(n))
思路二:如果用第6章的partition,

​ 如果partition的位置=k,就找到了

​ 如果partition的位置>k,在左边去找

​ 如果partition的位置<k,在右边去找k-partition的位置

int paritition(vector<int>& vec, int first, int last) {
	int i = first; int j = last;
	int val = vec[first];

	while (i < j) {
		while (vec[j] > val && i < j)
			j--;
		if (i < j)
			vec[i] = vec[j], ++i;
		while (vec[i] < val && i < j)
			++i;
		if (i < j)
			vec[j] = vec[i], --j;
	}
	vec[j] = val;
	return j;

}
int findKthSmallest1(vector<int>& vec,int k, int first, int last) {
	int partirionindex = paritition(vec, first, last);
	if (partirionindex > k)
		return findKthSmallest1(vec, k, first, partirionindex - 1);
	else if (partirionindex < k)
		return findKthSmallest1(vec, k, partirionindex + 1, last);
	else
		return vec[partirionindex];
}
int findKthSmallest(vector<int>& vec, int k) {
	return findKthSmallest1(vec, k - 1, 0, vec.size() - 1);
}
思路三:小根堆,所有元素都放到小根堆中,pop k个元素

​ O(klogn+logn)

int findKthSmallest(vector<int>& vec,int k) {
	priority_queue<int,vector<int>,greater<int>> pque;
	for (int i = 0; i < vec.size(); ++i) {
		pque.push(vec[i]);
	}
	int ans;
	for (int i = 0; i < k; i++) {
		ans = pque.top();
		pque.pop();
	}
	return ans;
}
思路四:大根堆,维护一个k大小的大根堆,如果当前元素比top要小的话,pop顶部,加入堆

​ O(k+(n-k)logk)

//面试官更倾向于让更面试者自己实现一个堆
//从上到下建立一个堆
void maxHeapify(vector<int>& a, int i, int heapSize) {
	if ( i>= HeapSize)return;
	int l = 2 * i + 1, r = i * 2 + 2, largest = i;
	if (l<heapSize && a[l]>a[largest])
		largest = l;
	if (r<heapSize && a[r]>a[largest])
		largest = r;
	if (largest != i) {
		swap(a[largest], a[i]);
		maxHeapify(a, largest, heapSize);
	}
}

void buildMaxHeap(vector<int>& a, int heapSize) {
	for (int i = heapSize / 2; i >= 0; --i) {
		maxHeapify(a, i, heapSize);
	}

}

int findKthLargest(vector<int>& nums, int k) {
	int size = nums.size();
	buildMaxHeap(nums, size);
	for (int i = nums.size() - 1; i >= nums.size() - k + 1; --i) {
		swap(nums[0], nums[i]);
		//把当前最大的和当前最小的进行交换
		--size;
		maxHeapify(nums,0, size);
	}
	return nums[0];
}
int findKthSmallest1(vector<int>& vec, int k) {
	priority_queue<int, vector<int>, less<int>> pque;

	int ans;
	for (int i = 0; i < k; i++) {
		pque.push(vec[i]);
	}
	for (int i = k; i < vec.size(); ++i) {
		if (vec[i] < pque.top()) {
			pque.pop();
			pque.push(vec[i]);
		}
	}
	ans = pque.top();
	return ans;
}
思路五:

对于选择排序,一定可以确定一个元素的最终位置,即 x 的最终位置为 q,并且保证 a[l … q - 1]a[l⋯q−1] 中的每个元素小于等于 a[q] ,且 a[q] 小于等于 a[q+1⋯r] 中的每个元素。所以只要某次划分的 q 为倒数第 k 个下标的时候,我们就已经找到了答案。 我们只关心这一点,至于 a[l⋯q−1] 和 a[q+1⋯r] 是否是有序的,我们不关心 .最坏的,时间代价是 O(n ^ 2 )。引入随机化来加速这个过程,它的时间代价的期望是 O(n)O(n),证明过程可以参考「《算法导论》9.2:期望为线性的选择算法」。
时间复杂度为 O(n)


int partition(vector<int>& a, int l, int r) {
	int cur = rand() % (r - l + 1) + l;
	swap(a[cur], a[r]); 
	int temp = l - 1;
	for (int i = l; i < r; ++i) {
		if (a[i] < a[r])
			swap(a[i], a[++temp]);
	}
	swap(a[r], a[temp + 1]);
	return temp+1;
}

//「快速选择」
//在分解的过程当中,我们会对子数组进行划分,如果划分得到的 q 正好就是我们需要的下标,就直接返回  a[q];
//否则,如果  q 比目标下标小,就递归右子区间,否则递归左子区间。 
//这样就可以把原来递归两个区间变成只递归一个区间,提高了时间效率。  


int quickSelect(vector<int>& a, int l, int r, int index) {
	int cur = partition(a, l, r);

	if (cur == index)return a[cur];
	return (cur < index) ? quickSelect(a, cur + 1, r,index) : quickSelect(a, l, cur - 1, index);
	
}


int findKthLargest(vector<int>& nums, int k) {
	srand(time(0));
	return quickSelect(nums, 0, nums.size() - 1, nums.size() - k);
}

Sort Colors 颜色分类

给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums ,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。

Given an array with n objects colored red, white or blue, sort them so that objects of the same color are adjacent, with the colors in the order red, white and blue. Here, we will use the integers 0, 1, and 2 to represent the color red, white, and blue respectively. Note: You are not suppose to use the library’s sort function for this problem. click to show follow up.

法一:计数法
void sortColors(vector<int>& vec) {
	const int len = vec.size();
	int cnt_Red = 0, cnt_White = 0, cnt_Bule = 0;
	for (int i = 0; i < len; ++i) {
		switch (vec[i])
		{
			case 0: {
				cnt_Red++; break;
			}
			case 1: {
				cnt_White++; break;
			}
			case 2: {
				cnt_Bule++; break;
			}
		}
	}

	for (int i = 0; i < len; ++i) {
		if (cnt_Red) {
			vec[i] = 0, cnt_Red--;
			continue;
		}
		if (cnt_White) {
			cnt_White--, vec[i] = 1;
			continue;
		}
		vec[i] = 2;
	}
	for (auto i : vec)
		cout << i << " ";
	cout << endl;
}
法二:两个指针移动
void sortColors1(vector<int>& vec) {
	const int n = vec.size();
	int redSt = 0, blueS = n - 1;

	int i = 0;
	while (i < blueS+1) {//终止条件注意!
		if (vec[i] == 0) {
			swap(vec[i], vec[redSt]);
			redSt++;
			++i;
			continue;
		}
		if (vec[i] == 2) {
			swap(vec[i], vec[blueS]);
			blueS--;
			continue;
		}
		++i;
	}
	for (auto i : vec)
		cout << i << " ";
	cout << endl;
}

8 LRU Cache问题,链表+HashMap

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8NtCNsm4-1663890274375)(C:\Users\13415\AppData\Roaming\Typora\typora-user-images\image-20220921071224184.png)]

LRU Cache
LinkedHashMap = DoulyLinkedList + HashMap 
HashMap<key, DoublyListNode> 
DoublyListNode { 
 prev, next, key, value; 
}

Newest node append to tail.

Eldest node remove from head

struct DLinkedNode {
 int key, value;
 DLinkedNode* prev;
 DLinkedNode* next;
 DLinkedNode(): key(0), value(0), prev(nullptr), next(nullptr) {}
 DLinkedNode(int _key, int _value): key(_key), value(_value), prev(nullptr), next(nullptr) {}
};

class LRUCache {
private:
 unordered_map<int, DLinkedNode*> cache;
 DLinkedNode* head;
 DLinkedNode* tail;
 int size;
 int capacity;

public:
 LRUCache(int _capacity): capacity(_capacity), size(0) {
     // 使用伪头部和伪尾部节点
     head = new DLinkedNode();
     tail = new DLinkedNode();
     head->next = tail;
     tail->prev = head;
 }
 
 int get(int key) {
     if (!cache.count(key)) {
         return -1;
     }
     // 如果 key 存在,先通过哈希表定位,再移到头部
     DLinkedNode* node = cache[key];
     moveToHead(node);
     return node->value;
 }
 
 void put(int key, int value) {
     if (!cache.count(key)) {
         // 如果 key 不存在,创建一个新的节点
         DLinkedNode* node = new DLinkedNode(key, value);
         // 添加进哈希表
         cache[key] = node;
         // 添加至双向链表的头部
         addToHead(node);
         ++size;
         if (size > capacity) {
             // 如果超出容量,删除双向链表的尾部节点
             DLinkedNode* removed = removeTail();
             // 删除哈希表中对应的项
             cache.erase(removed->key);
             // 防止内存泄漏
             delete removed;
             --size;
         }
     }
     else {
         // 如果 key 存在,先通过哈希表定位,再修改 value,并移到头部
         DLinkedNode* node = cache[key];
         node->value = value;
         moveToHead(node);
     }
 }

 void addToHead(DLinkedNode* node) {
     node->prev = head;
     node->next = head->next;
     head->next->prev = node;
     head->next = node;
 }
 
 void removeNode(DLinkedNode* node) {
     node->prev->next = node->next;
     node->next->prev = node->prev;
 }

 void moveToHead(DLinkedNode* node) {
     removeNode(node);
     addToHead(node);
 }

 DLinkedNode* removeTail() {
     DLinkedNode* node = tail->prev;
     removeNode(node);
     return node;
 }
};

  1. 去重问题,bitmap介绍

    Unique Count

    Give a big file with 32bits Integers(file size could be 10GB),however we only have machine with 1GB memory.Find the unique count of numbers.

    12,34,21,12,34====>3

    给一台普通的PC,1G内存,要求处理一个包含40亿个不重复并且没有排过序的无符号的int整数,给出一个整数,如果快速判断这个整数是否在文件40亿个数据中?

    40亿/32 < 512MB
    2^32/32=1e9,可以开出1e8的数组?(我的电脑只能1e5)
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PWOudyMJ-1663890274380)(C:\Users\13415\AppData\Roaming\Typora\typora-user-images\image-20220922075857569.png)]

    class myBitset {
    public:
    	myBitset(size_t N) {
    		_bits.resize(N / 32 + 1, 0);
    		_num = 0;
    	}
    	//将x位的bit设置为1
    	void set(size_t x) {
    		size_t index = x / 32;//算出x映射在第几个整形
    		size_t pos = x % 32;//算出x在整形的第几个位
    		_bits[index] |= (1 << pos);
    		++_num;
    	}
    	//将x位的bit设置为0
    	void reset(size_t x) {
    		size_t index = x / 32;
    		size_t pos = x % 32;
    		_bits[index] &= ~(1<<pos);
    		_num--;
    	}
    	//判断x位是否在不在
    	bool test(size_t x) {
    		size_t index = x / 32;
    		size_t pos = x % 32;
    
    		return _bits[index] & (1 << pos);
    	}
    	//位图中比特位的总个数
    	size_t size() {
    		return _num;
    	}
    private:
    	vector<int> _bits;
    	size_t _num;
    };
    

    位图的应用

    • 快速查找某个整形数据是否在一个集合中。
    • 排序。
    • 求两个集合的交集、并集等。
    • 操作系统中磁盘块标记。
  2. 搜索问题,倒排索引

    Query Search

    A library is trying to build up a smart computer-aided look up system: user may input a list of key words, and the system shall provide all books that contain these words. How to implement such query? (A library may have millions of books)

    apple -> doc1,doc2 banana -> doc2

  3. 分布式求和,MapReduce算法

Distributed Sum
MapReduce

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MacPXcvc-1663890274381)(C:\Users\13415\AppData\Roaming\Typora\typora-user-images\image-20220923070214204.png)]

Quick Questions
Trailing Number of zeros in n!

要求一个整数的阶乘末尾有多少个0;

//统计5的个数即可
int trailingZeroes_1(int n) {
	int res = 0;
	while (n != 0) {
		res += n / 5;
		n /= 5;//5的次方有多个5
	}
	return res;
}

O(1) Check Power of 2

//在O(1)的复杂度判断n是否为2的n次方
bool checkPowerOf2(int n) {
	if (1 > n)return false;
	return 0 == (n & (n - 1));//2的n次方与前一位相与为0
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值