//法一:贪心+二分搜索 intmaxPoint1(vector<int>& arr, int target){ int res = 1; for (int i = 0; i < arr.size(); i++) { int nearest = nearestIndex(arr, i, arr[i] - target); res = max(res, i - nearest + 1); } return res; } //二分搜索函数 intnearestIndex(vector<int>& arr, int R, int value){ int L = 0; int index = R; while (L < R) { int mid = L + (R- L) / 2; if (arr[mid] >= value) { index = mid; R = mid - 1; } else { L = mid + 1 } } return index; } //法二:贪心+双指针,滑动窗口 intmaxPoint1(vector<int>& arr, int target){ int left = 0, right = 0; int n = arr.size(); int count = 0; while (left < n) { while (right < n && arr[right] - arr[left] <= target) { right++; } count = max(count, right - left); left++; } return count; }
intminStep(string s){ if (s.size() == 0) return0; int step1 = 0; int gi = 0; //G在左边,B在右边 for (int i = 0; i< s.size(); i++) { if (s[i] == 'G') { step1 += i - gi; gi++; } } int step2 = 0; int bi = 0; //G在右边,B在左边 for (int i = 0; i< s.size(); i++) { if (s[i] == 'B') { step2 += i - bi; bi++; } } returnmin(step1,step2); }
publicMyHashMap(){ map = new HashMap<>(); time = 0; setAll = new MyValue<V>(null, -1); }
publicvoidput(K key, V value){ map.put(key, new MyValue<V>(value, time++)); }
publicvoidsetAll(V value){ setAll = new MyValue<V>(value, time++); }
public V get(K key){ if (!map.containsKey(key)) { returnnull; } if (map.get(key).time > setAll.time) { return map.get(key).value; } else { return setAll.value; } } }
06 最长无重复字串的子串长度
题目:
求一个字符串中,最长无重复字符子串长度
解析:
子串子数组问题,想每个i结尾时,满足条件的情况,无重复的子串长度dp[i]
从第i个位置向前推影响因素:某个位置与i位置的字符相同,或者i-1位置向左推的距离
可以滑动窗口
也可动态规划:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
intlengthOfLongestSubstring(string s){ if (s.size() == 0) return0; //acsii取值范围0~255 vector<int> map(256); //map存放上次出现的位置 for (int i = 0; i < 256; i++) { map[i] = -1; //初始默认出现在-1位置 } map[s[0]] = 0; int n = s.size(); int ans = 1; int pre = 1;//上一个位置,向左推了多长 for (int i = 1; i < n; i++) { pre = min(i - map[s[i]], pre + 1); ans = max(ans, pre); map[s[i]] = i; } return ans; }
//暴力解 intmaxPairNUm1(vector<int>& arr, int k){ if (k < 0) return-1; returnprocess1(arr, 0, k); } //暴力递归函数 intprocess1(vector<int>& arr, int index, int k){ int ans = 0; if (index == arr.size()) { //全排列 for (int i = 1; i < arr.size(); i += 2) { if (arr[i] - arr[i - 1] == k) { ans++; } } } else { for (int r = index; r < arr.size(); r++) { swap(arr[index], arr[r]); ans = max(ans, process1(arr, index + 1, k)); swap(arr[index], arr[r]); } } return ans; }
// 时间复杂度O(N*logN) intmaxPairNum2(vector<int>& arr, int k){ if (k < 0 || arr.size() < 2) return0; sort(arr.begin(), arr.end());//排序,满足单调性,先满足小值的情况 int ans = 0; int N = arr.size(); int L = 0, R = 0;//双指针窗口 vector<bool> usedR(N, 0); while (L < N && R < N) { if (usedR[L]) { L++; } elseif (L >= R) { R++; } else { // 不止一个数,而且都没用过! int dis = arr[R] - arr[L]; if (dis == k) { ans++; usedR[R++] = true; L++; } elseif (dis < k) { R++; } else { L++; } } } return ans; }
//法一: intnumRescueBoats1(vector<int>& arr, int limit){ if (arr.size() == 0) return0; int N = arr.size(); sort(arr.begin(), arr.end()); if (arr[N-1] > limit) return-1; int lessR = -1; for (int i = N -1; i >= 0; i--) { if (arr[i] <= limit / 2) { lessR = i; break; } } if (lessR == -1) return N; int L = lessR, R = lessR + 1; int noUsed = 0; while (L >= 0) { int solved = 0; while (R < N && arr[L] + arr[R] <= limit) { R++; solved++; } if (solved == 0) { noUsed++; L--; } else { L = max(-1, L - solved); } } int all = lessR + 1; int used = all - noUsed; int moreUnsolved = (N - all) - used; return used + ((noUsed + 1) >> 1) + moreUnsolved; } //法二:首尾双指针 intnumRescueBoats2(vector<int>& arr, int limit){ sort(arr.begin(), arr.end()); int ans = 0; int L = 0; int R = arr.size() - 1; int sum = 0; while (L <= R) { sum = L == R ? arr[L] : arr[L] + arr[R]; if (sum > limit) { R--; } else { L++; R--; } ans++; } return ans; }
09 子数组的最大累加和
题目描述:
返回一个数组arr中,子数组最大累加和
解析:
子数组以arr[i]结尾的最大累加和,求其最大值
dp[i] = max(dp[i - 1] + arr[i], arr[i])
1 2 3 4 5 6 7 8 9 10 11 12
intmaxSubArray(vector<int>& arr){ if (arr.size() == 0) return0; // 上一步,dp的值 // dp[0] int pre = arr[0]; int ans = arr[0]; for (int i = 1; i < arr.size(); i++) { pre = max(pre + arr[i], arr[i]); ans = max(pre, ans); } return ans; }
intcandy(vector<int>& arr){ if (arr.size() == 0) { return0; } int n = arr.size(); vector<int> left(n); for (int i = 1; i < n; i++) { if (arr[i] > arr[i - 1]) { left[i] = left[i - 1] + 1; } } vector<int> right(n); for (int i = n - 2; i >= 0; i--) { if (arr[i] > arr[i + 1]) { right[i] = right[i + 1] + 1; } } int ans = 0; for (int i = 0; i < n; i++) { ans += max(left[i], right[i]); } return ans + n; }