inlinefloatABS(constfloat n){ return n > 0 ? n : -n; }
floatnewton(float y, float epsilon=1e-5, int maxiter=20){ if (ABS(y) < epsilon) return0.0; float x = y, res; int cnt = 0; do { res = ABS(y - x * x); x -= (x * x - y) / (4.0 * x); cnt += 1; } while (cnt < maxiter && res > epsilon); return x; }
intfindKthLargest(vector<int>& nums, int k){ partition(nums, 0, nums.size() - 1, k); int ans = 0, dep = 1; return nums[nums.size() - k]; }
voidpartition(vector<int>& nums, int left, int right, int k){ if (left >= right) return; int lo = left, hi = right, basis = nums[lo]; while (lo < hi) { while (hi > lo && nums[hi] >= basis) -- hi; if (hi <= lo) break; nums[lo] = nums[hi]; while (lo < hi && nums[lo] <= basis) ++ lo; if (lo >= hi) break; nums[hi] = nums[lo]; } nums[lo] = basis; if (lo > nums.size() - k) { partition(nums, left, lo - 1, k); } elseif (lo < nums.size() - k) { partition(nums, lo + 1, right, k); } else { return; } }
Binary Search
240. Search a 2D Matrix II
Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties:
Integers in each row are sorted in ascending from left to right.
Integers in each column are sorted in ascending from top to bottom.
乍看像binary search,一旦思路被绕进binary search就出不来了。。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
boolsearchMatrix(vector<vector<int>>& matrix, int target){ int m = matrix.size(); if (m == 0) returnfalse; int n = matrix[0].size();
int row = 0, col = n - 1; while (row < m && col >= 0) { if (matrix[row][col] == target) returntrue; elseif (matrix[row][col] > target) { col--; } else { row++; } } returnfalse; }
4. Median of Two Sorted Arrays
There are two sorted arrays nums1 and nums2 of size m and n respectively.
Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).
You may assume A and B cannot be both empty.
头条最终面被问过的问题,显然是binary search,但是当时就是没想出来怎么写
Consider split indices i and j in array A and B correspondingly, visualizing as follows.
left_part
right_part
$A_{0},…,A_{i-1}$
$A_{i},…,A_{m-1}$
$B_{0},…,B_{j-1}$
$B_{j},…,b_{n-1}$
Provided that len(left_part) == len(right_part) and min(A[i], B[j]) >= max(A[i - 1], B[j - 1]), the split indices i and j must satisfy
deffindMedianSortedArrays(self, A, B): """ :type nums1: List[int] :type nums2: List[int] :rtype: float """ m, n = len(A), len(B) if m > n: A, B, m, n = B, A, n, m
imin, imax, half_len = 0, m, (m + n + 1) / 2 while imin <= imax: i = (imin + imax) / 2 j = half_len - i if i < m and B[j-1] > A[i]: # i is too small, must increase it imin = i + 1 elif i > 0and A[i-1] > B[j]: # i is too big, must decrease it imax = i - 1 else: # i is perfect if i == 0: max_of_left = B[j-1] elif j == 0: max_of_left = A[i-1] else: max_of_left = max(A[i-1], B[j-1])
if (m + n) % 2 == 1: return max_of_left
if i == m: min_of_right = B[j] elif j == n: min_of_right = A[i] else: min_of_right = min(A[i], B[j])
classSolution { public: stringlongestPalindrome(conststring& s){ if (s.size() <= 1) return s; int odd = 0, even = 0, ans = 0, axis; for (int i=0; i<s.size()-1; i++) { // Palindrome length is odd odd = expandPalindrome(s, i, i); // Palindrome length is even even = expandPalindrome(s, i, i + 1); if (odd > ans) { ans = odd; axis = i; } if (even > ans) { ans = even; axis = i; } } if (ans & 1) { return s.substr(axis - (ans >> 1), ans); } else { return s.substr(axis - (ans >> 1) + 1, ans); } } intexpandPalindrome(conststring& s, int axis, int raxis){ int left = axis, right = raxis; while (left >=0 && right < s.size() && s[left] == s[right]) { left --; right ++; } return right - left - 1; } };
219. Contains Duplicate II
Easy难度的题,题意如下
Given an array of integers and an integer k, find out whether there are two distinct indices i and j in the array such that nums[i] = nums[j] and the absolute difference between i and j is at most k.
最简单直接的做法是每次迭代开一个大小为k的滑动窗口来查找,复杂度$O(kN)$
1 2 3 4 5 6 7 8 9 10 11
boolcontainsNearbyDuplicate(vector<int>& nums, int k){ if (nums.empty()) returnfalse; for (int i=0; i<nums.size(); i++) { for (int j=i+1; j<nums.size() && j-i<=k; j++) { if (nums[j] == nums[i]) returntrue; } } returnfalse; }
boolcontainsNearbyDuplicate(vector<int>& nums, int k){ if (nums.empty()) returnfalse; if (k >= nums.size()) k = nums.size() - 1; set<int> table(nums.begin(), nums.begin() + k + 1); if (table.size() != k + 1) returntrue; for (int i=k+1; i<nums.size(); i++) { table.erase(nums[i - k - 1]); if (table.find(nums[i]) != table.end()) returntrue; table.insert(nums[i]); } returnfalse; }
220. Contains Duplicate III
Given an array of integers, find out whether there are two distinct indices i and j in the array such that the absolute difference between nums[i] and nums[j] is at most t and the absolute difference between i and j is at most k.
classSolution { public: boolcontainsNearbyAlmostDuplicate(vector<int>& nums, longlong k, longlong t){ if (nums.empty() || t < 0) returnfalse; if (k >= nums.size()) k = nums.size() - 1; set<longlong> table(nums.begin(), nums.begin() + k + 1); if (table.size() != k + 1) returntrue; for (auto it=table.begin(); it!=table.end(); it++) { auto cmp = it; cmp ++; if (cmp != table.end() && *cmp - *it <= t) returntrue; } for (int i=k+1; i<nums.size(); i++) { table.erase(nums[i - k - 1]); auto it = table.lower_bound(nums[i]), jt = it; if (it != table.end() && *it - nums[i] <= t) returntrue; if (jt != table.begin()) { jt --; if (nums[i] - *jt <= t) returntrue; } table.insert(nums[i]); } returnfalse; } };
11. Container With Most Water
很有趣的一道题,思路很巧妙,代码意外地非常简单。
Given n non-negative integers a1, a2, …, an , where each represents a point at coordinate (i, ai). n vertical lines are drawn such that the two endpoints of line i is at (i, ai) and (i, 0). Find two lines, which together with x-axis forms a container, such that the container contains the most water.
Note: You may not slant the container and n is at least 2.
1 2 3 4 5 6 7 8 9 10 11
intmaxArea(vector<int>& height){ int maxarea = 0, left = 0, right = height.size() - 1; while (left < right) { maxarea = max(maxarea, min(height[left], height[right]) * (right - left)); if (height[left] < height[right]) left ++; else right --; } return maxarea; }
How this approach works?
Initially we consider the area constituting the exterior most lines. Now, to maximize the area, we need to consider the area between the lines of larger lengths. If we try to move the pointer at the longer line inwards, we won’t gain any increase in area, since it is limited by the shorter line. But moving the shorter line’s pointer could turn out to be beneficial, as per the same argument, despite the reduction in the width. This is done since a relatively longer line obtained by moving the shorter line’s pointer might overcome the reduction in area caused by the width reduction.
设事件$A_{k}=\{\text{Node k is put into the buffer}\}$,$B_{k}^{i}=\{\text{Node k is replaced by node i}\}$,$R_{k}=\{\text{Node k is returned as a sampled node}\}$,设链表总结点数为$N$,那么链表中第$k$个节点最终被返回的概率为
classSolution { public: /** @param head The linked list's head. Note that the head is guaranteed to be not null, so it contains at least one node. */ Solution(ListNode* _head): head(_head) {} /** Returns a random node's value. */ intgetRandom(){ ListNode *p = head, *ans = head; float prob = 1.0; while (p != NULL) { float epsilon = float(rand()) / float(RAND_MAX); if (epsilon < (1.0 / prob)) ans = p; prob += 1.0; p = p->next; } return ans->val; } private: ListNode *head; };