算法:经典leetcode算法题解

索引
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)

给定一个有序正整数数组nums以及一个整数n,向数组中添加/补充一些元素,使其“部分元素和”可以组成范围[1, n]内的所有数字。返回最少需要添加的元素个数。

Example 1:
nums = [1, 3], n = 6
Return 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.
经典解法:

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
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值