算法:经典leetcode算法题解

来源:互联网 发布:c程序编写软件 编辑:程序博客网 时间:2024/05/21 17:08
索引
1. https://leetcode.com/problems/patching-array/  补丁数组
2. https://leetcode.com/problems/find-the-duplicate-number/ 找出重复元素
3. https://leetcode.com/problems/majority-element-ii/  找出主元素 (O(n))
4. https://leetcode.com/problems/lru-cache/  LRU Cache (链表)
5. https://leetcode.com/problems/sliding-window-maximum/ 滑动窗口-单调队列
6. https://leetcode.com/problems/largest-rectangle-in-histogram/(单调栈,可看)
7. https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iii/ 股票最大收益(动态规划)
8. https://leetcode.com/problems/distinct-subsequences/  找不同序列(动态规划)
9. https://leetcode.com/problems/h-index/     H指数计算
10. https://leetcode.com/problems/find-minimum-in-rotated-sorted-array/  旋转有序数组中找最小元素
11. https://leetcode.com/tag/depth-first-search/  深度优先搜索

1. Patching Array 补丁数组(考虑ing)

原题描述:https://leetcode.com/problems/patching-array/
给定一个有序正整数数组nums以及一个整数n,向数组中添加/补充一些元素,使其“部分元素和”可以组成范围[1, n]内的所有数字。返回最少需要添加的元素个数。Example 1:nums = [1, 3], n = 6Return 1.Combinations of nums are [1], [3], [1,3], which form possible sums of: 1, 3, 4.Now if we add/patch 2 to nums, the combinations are: [1], [2], [3], [1,3], [2,3], [1,2,3].Possible sums are 1, 2, 3, 4, 5, 6, which now covers the range [1, 6].So we only need 1 patch.
经典解法:
C++版本:http://blog.csdn.net/murmured/article/details/50596403
Python版本:http://bookshadow.com/weblog/2016/01/27/leetcode-patching-array/

2. Find the Duplicate Number 寻找重复数 (龟兔赛跑、二分法)

原题描述:https://leetcode.com/problems/find-the-duplicate-number/

主要思路:https://segmentfault.com/a/1190000003817671

代码详解:http://bookshadow.com/weblog/2015/09/28/leetcode-find-duplicate-number/

题外记:

int值域 4字节 - 2147 438 648~+ 2 147 438 647 

long int 4字节 - 2 147 438 648 ~ + 2 147 438 647

long long int 8 - 9 223 372 036 854 775 808 ~ + 9 223 372 036 854 775 807


3. Majority Element II 多数投票算法

原题描述:https://leetcode.com/problems/find-the-duplicate-number/

Given an integer array of size n, find all elements that appear more than ⌊ n/3 ⌋ times. The algorithm should run in linear time and in O(1) space.

主要思路:摩尔投票法。找到数量和大于n/2的两个数。然后判断哪个符合条件。

代码详解:http://www.cnblogs.com/ZhangYushuang/p/4627503.html

题外记:Majority Element——如果是⌊ n/2⌋。考虑用 Moore’s Voting Algorithm算法,http://blog.csdn.net/booirror/article/details/42738563


4. LRU Cache(数据结构设计)


原题描述:https://leetcode.com/problems/lru-cache/

题目大意:为LRU Cache设计一个数据结构,它支持两个操作:   1)get(key):如果key在cache中,则返回对应的value值,否则返回-1   2)set(key,value):如果key不在cache中,则将该(key,value)插入cache中(注意,如果cache已满,则必须把最近最久未使用的元素从cache中删除);如果key在cache中,则重置value的值。
主要思路:http://www.cnblogs.com/dolphin0520/p/3741519.html

单链表:O(n)

#include <iostream>#include <map>#include <algorithm>using namespace std; struct Node{    int key;    int value;    Node *next;};class LRUCache{private:    int count;    int size ;    map<int,Node *> mp;    Node *cacheList;public:    LRUCache(int capacity) {      size = capacity;      cacheList = NULL;      count = 0;    }       int get(int key) { }     void set(int key, int value) { }      void pushFront(Node *cur){   //单链表删除节点,并将节点移动链表头部,O(n)、O(1)}      }}

双链表:O(1)

#include <iostream>#include <map>#include <algorithm>using namespace std; struct Node{    int key;    int value;    Node *pre;    Node *next;};class LRUCache{private:    int count;    int size ;    map<int,Node *> mp;    Node *cacheHead;    Node *cacheTail;public:    LRUCache(int capacity) {      size = capacity;      cacheHead = NULL;      cacheTail = NULL;      count = 0;    }         int get(int key) {}    void set(int key, int value) {}    void pushFront(Node *cur){   //双向链表删除节点,并将节点移动链表头部,O(1)}}int main(void){    LRUCache cache(3);    cache.set(1,1);}

题外记1:最全的c++map的用法

题外记2:it->second表示取键值。

map<string, int> m;m["one"] = 1;map<string, int>::iterator p = m.begin();p->first; // 这个是 string 值是 "one"p->second; //这个是 int 值是 1

题外记3:

序列性容器用erase:iter = c.erase(iter);   //删除并防止迭代器失效

关联性容器用erase:mp.erase(iter++);   //只是被删元素的迭代器失效,但是返回值为void


5. Sliding Window Maximum 滑动窗口最大值(单调队列)


原题描述:https://leetcode.com/problems/sliding-window-maximum/

主要思路:

优先队列——时间 O(NlogK) 空间 O(K)。维护一个大小为K的最大堆,依此维护一个大小为K的窗口,每次读入一个新数,都把堆中窗口最左边的数扔掉,再把新数加入堆中,这样堆顶就是这个窗口内最大的值。

双向队列——时间 O(N) 空间 O(K)。

            // 每当新数进来时,如果发现队列头部的数的下标,是窗口最左边数的下标,则扔掉

            // 把队列尾部所有比新数小的都扔掉,保证队列是降序的

            // 加入新数

            // 队列头部就是该窗口内第一大的

代码详解:https://segmentfault.com/a/1190000003903509

题外记:peek() 方法用于检索队列的头部。但它不会将其删除。


6. Largest Rectangle in Histogram 直方图最大面积)(单调栈)


原题描述:https://leetcode.com/problems/largest-rectangle-in-histogram/

主要思路:

1、如果已知height数组是升序的,应该怎么做?

比如1,2,5,7,8,那么就是(1*5) vs. (2*4) vs. (5*3) vs. (7*2) vs. (8*1),也就是max(height[i]*(size-i))

2、使用栈的目的就是构造这样的升序序列,按照以上方法求解。

代码详解:http://www.cnblogs.com/ganganloveu/p/4148303.html


7. Best Time to Buy and Sell Stock III(DP)


原题描述:https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iii/

主要思路:动态规划法。以第i天为分界线,计算第i天之前进行一次交易的最大收益preProfit[i],和第i天之后进行一次交易的最大收益postProfit[i],最后遍历一遍,max{preProfit[i] + postProfit[i]} (0≤i≤n-1)就是最大收益。第i天之前和第i天之后进行一次的最大收益求法同Best Time to Buy and Sell Stock I。

preProfit[i] = Math.max(preProfit[i - 1], prices[i] - curMin);

postProfit[i] = Math.max(postProfit[i + 1], curMax - prices[i]);

maxProfit = Math.max(maxProfit, preProfit[i] + postProfit[i]);

代码详解:http://liangjiabin.com/blog/2015/04/leetcode-best-time-to-buy-and-sell-stock.html

题外话:DP算法是解决多阶段决策过程最优化问题的一种常用方法。

多阶段决策过程(multistep decision process)是指这样一类特殊的活动过程,过程可以按时间顺序分解成若干个相互联系的阶段,在每一个阶段都需要做出决策,全部过程的决策是一个决策序列。

动态规划(dynamic programming)算法是解决多阶段决策过程最优化问题的一种常用方法,难度比较大,技巧性也很强。


8. Best Time to Buy and Sell Stock III(DP)


原题描述:https://leetcode.com/problems/distinct-subsequences/

代码详解:http://www.tuicool.com/articles/6BZRJf


9. H-Index H因子(二分?)


原题描述:https://leetcode.com/problems/h-index/

代码详解:http://www.thinksaas.cn/group/topic/395874/ (Java版)


10.  Find Minimum in Rotated Sorted Array(二分)


原题描述:https://leetcode.com/problems/find-minimum-in-rotated-sorted-array/

代码详解:http://www.cnblogs.com/x1957/p/4028271.html

class Solution {public:    int findMin(vector<int> &num) {        int size = num.size() - 1;        int l = 0;        int r = size;        while(l <= r) {            int mid = l + (r - l) / 2;            if (num[mid] > num[size]) {                //left                l = mid + 1;            } else {                r = mid - 1;            }        }        return num[l];    }};

11. Depth-first Search


原题列表:https://leetcode.com/tag/depth-first-search/

DFS通用代码:http://www.cnblogs.com/PegasusWang/archive/2013/04/06/3002511.html

void bfs(int v)20 {21     list<int>::iterator it;22     printf("%5d", v);23     visited[v] = true;24     queue<int> t;25     t.push(v);26     while (!t.empty())27     {28         v = t.front();29         t.pop();30         for (it = graph[v].begin(); it != graph[v].end(); ++it)31             if (!visited[*it])32             {33                 printf("%5d", *it);34                 t.push(*it);35                 visited[*it] = true;36             }37     }38     cout << endl;39 }


特此感谢Jacky.Mao。

0 0