斯坦福 算法1 第三周作业

斯坦福 Algorithms: Design and Analysis 1 第三周作业

    • 1 Problem Set 3
    • 2 Optional Theory Problems
    • 3 Programming Assignment 3
    • 4 彩蛋:Linear Selection 实现

来自斯坦福网站的Algorithms: Design and Analysis,与目前coursera上的版本内容没有变化,不过时间安排略有不同。

1 Problem Set 3

斯坦福 算法1 第三周作业_第1张图片
作为树的图最小割的个数。这是最小割的交叉边是1,对应每条边都是一个交叉边,也就是对应一个最小割。

斯坦福 算法1 第三周作业_第2张图片
当图对应是一个环时,前三个都满足,概率就是p,也就对应着最大数量的最小割。但是并非所有的图都存在这样的最小割,根据推导,一般情况都是大于等于p。

斯坦福 算法1 第三周作业_第3张图片
显然。

斯坦福 算法1 第三周作业_第4张图片
每次留下 α \alpha αn的数量,直到1为止。

斯坦福 算法1 第三周作业_第5张图片
固定一个点,遍历对应n-1的组合。在这n-1个组合里比如有至少一个是两个点分别在A和B中。

2 Optional Theory Problems

斯坦福 算法1 第三周作业_第6张图片
1 一脸懵逼。看了这个链接里的解释大概懂了吧。ppt中已经证明了某个确定性的算法的复杂度是 Ω ( n l o g n ) \Omega(nlogn) Ω(nlogn),要做的就是将随机性算法转化为确定性的概率和。假设某个随机性算法中的一种运行情况对应随机事件s,概率为 P r ( s ) Pr(s) Pr(s)。而这种运行情况相当于一个确定性算法,因此随机算法的复杂度为 ∑ s P r ( s ) Ω ( n l o g n ) = Ω ( n l o g n ) \sum_{s}Pr(s)\Omega(nlogn) = \Omega(nlogn) sPr(s)Ω(nlogn)=Ω(nlogn),因此得证。具体可以看链接中的解释。
2 7是可以的,但3不可以。主要区别在于如下过程中证明的部分:

斯坦福 算法1 第三周作业_第7张图片
这里如果改为7,那么对应的两个数字就是n/7与5n/7,依然可以成立。然而对应3的n/3与2n/3不能让不等式成立。

3 用 O ( n ) O(n) O(n)的方法计算权重中位数。想了半天以为是转化为linear selection,没想出来。没想到是直接类似linear selection做个新算法。伪代码如下:
斯坦福 算法1 第三周作业_第8张图片
思路如下:1. 先找到x数组的中位数x[k]。2. 计算小于x[k]的x对应的系数w之和。如果大于一半则保留下小于x[k]的x与对应的w,递归计算。否则保留大于x[k]的部分。

4 感觉依然是多项式表示的,不过最多是n个。写了个证明不知道是否正确:

  • 有向图中最小割的交叉边数量依然为k。而每个边的出度大于等于k。因此 n k ≤ m nk\leq m nkm
  • Pr(第i步选不到交叉边|第i-1步选不到交叉边) = n − i n \dfrac{n-i}{n} nni
  • 因此Pr(结果是最小割)= 1 n \dfrac{1}{n} n1

因此有向图中最小割个数最多是n个。证明过程有些简陋,对照ppt看吧。

5 这只要在证明的时候每个概率的地方加上 α \alpha α,最后结果 P r ( 一 次 算 法 结 果 是 α − m i n i m u m − c u t ) = 2 α n − 2 n ( n − 1 ) Pr(一次算法结果是\alpha-minimum-cut) = \dfrac{2\alpha^{n-2}}{n(n-1)} Pr(αminimumcut)=n(n1)2αn2,于是上限就是这个概率的倒数。

3 Programming Assignment 3

实现一个压缩最小割算法。很蛋疼,debug了很久。
斯坦福 算法1 第三周作业_第9张图片
实现如下:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;

unordered_map> readGraph(string fileName) {
    cout << "read data from "<< fileName <> linkedLists;
    int tmp;
    int v;
    if(input) {
        while(getline(input,line)) {
            vector dl;
            istringstream ist(line);
            ist >> v;
            while(ist >> tmp)
                dl.push_back(tmp);
            linkedLists[v] = dl;
        }
    }
    return linkedLists;
}

int contraction_one(unordered_map> graph, vector edges) {
    int index;
    while(graph.size() > 2) {
        index = rand()%edges.size();//选一个边
        int rem = edges[index]/1000, del = edges[index]%1000;//将节点del合并到rem

        if(graph.find(rem) == graph.end() || graph.find(del) == graph.end()) {
            cout << "wrong"<>& graph, vector& edges) {
    cout << "contraction start..."<> graph;
    graph = readGraph("kargerMinCut.txt");
    vector edges;
    for(auto& k : graph)
        for(int x : k.second)
            edges.push_back(k.first*1000+x);
    contraction(graph,edges);
    return 0;
}

用了两个结构表示图,一个是邻接表,一个是边的vector。每个边用一个整数表示,1000×a+b。由于是无向图,每个边都有(a,b)和(b,a)两个,很容易代码就会漏掉。核心部分都有注释,应该看得懂。

4 彩蛋:Linear Selection 实现

用了随机性选择的算法,正好是leetcode 215题,实现方式是三路partition(考虑重复元素),AC代码如下:

class Solution {
public:
    int findKthLargest(vector& nums, int k) {
        return helper(nums,0,nums.size(),k);
    }
    
    int helper(vector& nums, int begin, int end, int k) {
        if(k == 1 && begin+1 == end) return nums[begin];
        int pivot = nums[begin];
        int left = begin+1, mid = left, right = mid;
        while(right < end) {
            if(nums[right] == pivot) {
                swap(nums[right],nums[mid]);
                mid++;
            }else if(nums[right] > pivot) {
                swap(nums[right],nums[left]);
                if(mid > left)
                    swap(nums[right],nums[mid]);
                left++;
                mid++;
            }
            right++;
        }
        swap(nums[begin],nums[left-1]);
        if(k-1 >= left-begin && k-1 < mid-begin)
            return pivot;
        else if(k-1 < left-begin)
            return helper(nums,begin,left,k);
        else
            return helper(nums,mid,end,k-mid+begin);
    }
};

神奇的是,这个说好的平均 O ( n ) O(n) O(n)算法比直接用stl的sort还慢。emmm,就这样吧。

你可能感兴趣的:(数据结构与算法)