卜东坡算法-2021秋作业1-分治

警告
本文最后更新于 2022-12-11,文中内容可能已过时。

2021秋作业1-分治

1. 找出整数数组中第K大的数

215.Kth Largest Element in an Array (Medium)

Given an integer array nums and an integer k, please return the k-th largest element in the array. Your algorithm’s runtime complexity must be in the order of O(n), prove the correctnes-sand analyze the complexity.(k is much smaller than n, n is the length of the array.)

Example 1:

1
2
Input: nums = [3,2,1,5,6,4], k = 2
Output: 5

Example 2:

1
2
Input: nums = [3,2,3,1,2,4,5,5,6], k = 4
Output: 4

Constraints:

  • 1 <= k <= nums.length <= 104

  • -104 <= nums[i] <= 104

Solution:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        int idx = 0;
        vector<int> numL;
        vector<int> numR;
        for (int i = idx + 1; i < nums.size(); i++) {
            if (nums[i] > nums[idx]) {
                numR.push_back(nums[i]);
            } else {
                numL.push_back(nums[i]);
            }
        }
        if (numR.size() == k - 1) {
            return nums[idx];
        } else if (numR.size() > k - 1) {
            return findKthLargest(numR, k);
        } else {
            return findKthLargest(numL, k - numR.size() - 1);
        }
    }
};

(Page55)Complexity:

如果子实例处在$[n(\frac 34) ^{j + 1} + 1, n(\frac 34) ^{j}]$则说明 算法运行在第$j$期,$X$表示算法整体的元素比较次数,$X_j$表示运行过程处于第j期时的比较次数,则有:

​ $$X = X_0 + X_1 + X_2 + \dots$$

选择中间区域的概率为$\frac 12$,选择一个中间区域的元素作为中心元后,实例规模减少$\frac 1 4$,因为每一期递归调用期望是两次,则在第$j$期的时候算法期望比较次数为$2n(\frac{3}{4})^j$,则整体的期望比较次数为:

​ $$E(X)=E[X_0 +X_1+X_2+\dots] \leq \sum_j 2cn (\frac 34)^j \leq 8cn$$

则时间复杂度为$O(n)$。

2. 二叉树邻域最小值

Consider an $n$-node complete binary tree $T$, where $n = 2^d − 1$ for some $d$. Each node $v$ of $T$ is labeled with a real number $x_v$. You may assume that the real numbers labeling the nodes are all distinct. A node $v$ of $T$ is a local minimum if the label $x_v$ is less than the label $x_w$ for all nodes $w$ that are joined to v by an edge. You are given such a complete binary tree T, but the labeling is only specified in the following: implicit way: for each node v, you can determine the value xv by probing the node v.

Show how to find a local minimum of T using only O(logn) probes to the nodes of T.

解法:

3. 数组子数组最大和

1800.Maximum Ascending Subarray Sum (Easy)

Given an integer array, one or more consecutive integers in the array form a sub-array. Find the maximum value of the sum of all subarrays. Please give an algorithm with O(nlogn) complexity

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Solution {
public:
    int findLargestSubArraySum(vector<int>& nums, int start, int end) {
        if (start == end) {
            return nums[start];
        } else if (start > end) {
            return -1;
        }
        int mid = (start + end) / 2;
        int subStart = mid;
        int subSum = nums[mid];
        while (subStart > start && nums[subStart] - 1 == nums[subStart - 1]) {
            subStart--;
            subSum += nums[subStart];
        }
        int subEnd = mid;
        while (subEnd < end && nums[subEnd] + 1 == nums[subEnd + 1]) {
            subEnd++;
            subSum += nums[subEnd];
        }
        int subLSum = findLargestSubArraySum(nums, start, subStart - 1);
        int subRSum = findLargestSubArraySum(nums, subEnd + 1, end);
        return max(max(subSum, subLSum), subRSum);
    }
};

4. 查找有序数组指定元素的区间

34.find-first-and-last-position-of-element-in-sorted-array (Medium)

Given an array of integers nums sorted in non-decreasing order, find the starting and ending position of a given target value.

If target is not found in the array, return [-1, -1].

You must write an algorithm with O(log n) runtime complexity.

Example 1:

1
2
Input: nums = [5,7,7,8,8,10], target = 8
Output: [3,4]

Example 2:

1
2
Input: nums = [5,7,7,8,8,10], target = 6
Output: [-1,-1]

Example 3:

1
2
Input: nums = [], target = 0
Output: [-1,-1]
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        int l = findFisrt(nums, target);
        int h = findFisrt(nums, target + 1);
        if (l == nums.size() || nums[l] != target) {
            return vector<int> {-1, -1};
        }
        return vector<int> {l, h - 1};
    }
    int findFisrt(vector<int>& nums, int target) {
        int l = 0;
        int h = nums.size();
        while (l < h) {
            int mid = (l + h) / 2;
            if (nums[mid] >= target) {
                h = mid;
            } else {
                l = mid + 1;
            }
        }
        return l;
    }
};

5. 求N多边形可以被切割成多少个三角形

Given a convex polygon with n vertices, we can divide it into several separated pieces, such that every piece is a triangle. When n = 4, there are two different ways to divide the polygon; When n = 5, there are five different ways.

Give an algorithm that decides how many ways we can divide a convex polygon with n vertices into triangles.

6. 归并K个长度为N的有序链表

Given an array of k linked-lists lists, each linked-list is sorted in ascending order. Given an O(knlogk) algorithm to merge all the linked-lists into one sorted linked-list. (Note that the length of a linked-lists is n)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class Solution {
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        return helpMergeKLists(lists, 0, lists.size() - 1);
    }
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        ListNode* head = new ListNode(-1);
        ListNode* p = head;
        while (l1 != NULL || l2 != NULL) {
            if (l1 == NULL && l2 != NULL) {
                p->next = l2;
                l2 = l2->next;
            }
            if (l1 != NULL && l2 == NULL) {
                p->next = l1;
                l1 = l1->next;
            }
            if (l1 != NULL && l2 != NULL) {
                p->next = l1->val > l2->val ? l2 : l1;
                l1->val > l2->val ? l2 = l2->next : l1 = l1->next;
            }
            p = p->next;
        }
        return head->next;
    }
    ListNode* helpMergeKLists(vector<ListNode*>& lists, const int& start, const int& end) {
        if (start > end) {
            return NULL;
        } else if (start == end) {
            return lists[start];
        }
        int mid = (start + end) / 2;
        ListNode* l1 = helpMergeKLists(lists, start, mid);
        ListNode* l2 = helpMergeKLists(lists, mid + 1, end);
        return mergeTwoLists(l1, l2);
    }

};

7.Fast Mod Exponentiation

Description

Bob has encountered a difficult problem, and hope you design

an algorithm to calculate pow(a,b) mod 1337, where a is a positive

integer, b is a very large positive integer and will be given in the

form of an array. For example, pow(2,3) mod 1337 is 8.

1 \le a \le 2^{31} - 1,1≤a≤231−1,

1 \le b.length \le 2000,1≤b.lengt**h≤2000,

0 \le b[i] \le 90≤b[i]≤9

bb doesn’t contain leading zeros.

Please give an algorithm with O(\log n)O(logn) complexity.

Input

Line 1: integers

Line 2: an array

Output

One integer

Sample Input 1

1
2
2
[3]

Sample Output 1

1
8

Sample Input 2

1
2
4
[3,5]

Sample Output 2

1
709

Sample Input 3

1
2
222222222
[4,0,0]

Sample Output 3

1
1171
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <stdio.h>
#define MOD_VALUE 1337
int size = 0;
int start = 0;
int count = 0;
int array[2000];
void arrayHalfDivide()
{
    array[size - 1] = array[size - 1] / 2;
    int i = size - 2;
    while (i >= start) {
        int curr = array[i] * 5;
        array[i] = curr / 10;
        array[i + 1] += curr % 10;
        --i;
    }
    if (array[start] == 0 && count > 1) {
        count--;
        start++;
    }
}
int clacFastModExponentation(int base)
{
    if (count == 1 && array[size - 1] == 0) {
        return 1;
    }
    if (count == 1 && array[size - 1] == 1) {
        return base % MOD_VALUE;
    }
    int sumMod = 1;
    if (array[size - 1] % 2 != 0) {
        array[size - 1] = array[size - 1] - 1;
        sumMod *= (base % MOD_VALUE);
    }
    arrayHalfDivide();
    int currMod = clacFastModExponentation(base) % MOD_VALUE;
    sumMod *= (currMod * currMod) % MOD_VALUE;
    return sumMod % MOD_VALUE;
}
int main()
{
    int base;
    scanf("%d", &base);
    char ch;
    while ((ch = getchar()) && ch != ']') {
        if (ch >= '0' && ch <= '9') {
            array[size++] = ch - '0';
            count++;
        }
    }
    printf("%d\n", clacFastModExponentation(base));
    return 0;
}
0%