Tuesday, February 27, 2018

LeetCode 225 Implement Stack using Queues

#**LeetCode225**
---
https://leetcode.com/problems/implement-stack-using-queues/description/

Yifeng Zeng

#题目描述
---
Implement Stack using Queues

#思路报告
---
拿到这个题,先分析Stack和Queue的性质,stack是FILO,queue是FIFO,那么只放一个数(假设为1)进queue和进stack其实没有区别。那么再放第二个数(假设为2)的时候,先进的那个数1其实需要放到现在放的这个数2的后面,那么下一次从queue里面拿出来就可以先拿出2了。所以做push操作的时候我们用另外一个queue(help)把要push的数(前面提到的2)先暂存一下,然后把queue(真正的data)里面的数全部放入help queue,这样的顺序就是FILO了,再把help queue里面的数放回data queue以便下一次操作。那么做pop,top的时候只需要做data queue的poll,peek操作了。


代码如下

```java
class MyStack {

    Deque<Integer> dataQ;
    Deque<Integer> helpQ;
    /** Initialize your data structure here. */
    public MyStack() {
        dataQ = new LinkedList<>();
        helpQ = new LinkedList<>();
    }

    /** Push element x onto stack. */
    public void push(int x) {
        helpQ.offer(x);
        while (!dataQ.isEmpty()) {
            helpQ.offer(dataQ.poll());
        }
        while (!helpQ.isEmpty()) {
            dataQ.offer(helpQ.poll());
        }
    }

    /** Removes the element on top of the stack and returns that element. */
    public int pop() {
        return dataQ.poll();
    }

    /** Get the top element. */
    public int top() {
        return dataQ.peek();
    }

    /** Returns whether the stack is empty. */
    public boolean empty() {
        return dataQ.isEmpty();
    }
}
```

#套路总结
---
- 这个貌似没感觉到有什么套路,既然题目是用queue implement stack,而一个queue明显不够用,就用两个queue,在想想stack queue操作顺序的不同就可以解出来了

LeetCode 56 Merge Intervals

#**LeetCode56**
---
https://leetcode.com/problems/merge-intervals/description/

Yifeng Zeng

#题目描述
---
Merge Intervals

#思路报告
---

如果要merge a list of intervals,我们首先想到的是在这个list里面选两个interval来merge,那么就是两个for循环,O(n^2)。对于每一对interval: i1,i2,我们要看i1.start是否在[i2.start, i2.end]之间,还要看i2.star是否在[i1.start, i1.end]之间。那么能不能提速呢?能不能只检查一半,即只检查i1.start是否在[i2.start, i2.end]之间呢?可以,只要我们保证i1.start >= i2.start就可以了。怎样保证呢?我们可以把所有的intervals按照i.start排序就好了,那么sort的时间就是O(nlogn)。所以我们要自己写一个Interval的comparator。那么假设intervals已经排好序了,我们还需要两个for循环做O(n^2)的时间吗?明显不用,我们只需要把第一个interval拿出来(假设为prev),作为一个base case,再拿后面的interval拿出来(假设为cur)跟它比较。因为我们已经排序了,所以一定有prev.start <= cur.start,那么我们只用检查cur.end是否小于等于pre.end,如果是,那么我们可以merge,如果不是,证明prev不会有其他的可以merge了,因为后面的i.start也一定大于等于pre.end。那么我们就可以把这个prev放在result里面了。但是我们要注意的是,最后一个prev,它将不再会有其他的interval跟它比较了,所以也要把它放到result里面,就刚跟LC186最后一个word类似。所以我们把merge的时间复杂度降到了O(n),但是排序用了O(nlogn),所以整个算法的时间复杂度是O(nlogn)。

代码如下:
```java
class Solution {
    Comparator<Interval> myComparator = new Comparator<Interval>() {
        @Override
        public int compare(Interval o1, Interval o2) {
            return o1.start - o2.start;
        }
    };
    public List<Interval> merge(List<Interval> intervals) {
        List<Interval> res = new ArrayList<>();
        if (intervals == null || intervals.size() == 0) {
            return res;
        }
        Collections.sort(intervals, myComparator);
        Interval prev = intervals.get(0);
        for (int i = 1; i < intervals.size(); i++) {
            Interval cur = intervals.get(i);
            if (cur.start <= prev.end) {
                prev.end = Math.max(prev.end, cur.end);
            } else {
                res.add(prev);
                prev = cur;
            }
        }
        res.add(prev);
        return res;
    }
}
```


#套路总结
---
- 我们从最暴力的O(n^2)看出来,两个interval相互比较能不能merge,想到能否只比较一边,从而想到排序。
- 当输入杂乱无章的时候可以考虑排序,固定一端检查另一端。
- 空间复杂度???
  - 其实我的理解是作为输出的space不计入复杂度,那么就是O(1),但是这个res确实是extra的,由于输入是List,那么我们想要在它本身里面去merge后删除一个interval其实代价也是O(n),那么对List做“inplace”操作反而效率不高,所以就直接另外new了一个List,这点可以跟面试官讨论。

LeetCode 186 Reverse Words in a String II

#**LeetCode186**
---
https://leetcode.com/problems/reverse-words-in-a-string-ii

Yifeng Zeng

#题目描述
---
Reverse Words in a String II
![](186.png)

#思路报告
---

最开始我是做的Lintcode的53题http://www.lintcode.com/en/problem/reverse-words-in-a-string/
输入输出都是String而不是char[],当时的思路是用String[] strs = s.split(" ");把输入String分成多个word。因为String在Java里面本来就是immutable的,所以这需要extra O(n)的space,然后输出也是String,所以可以直接用一个StringBuilder把Sting[] strs,从后往前拼接起来中间加空格即可,然后返回StringBuilder.toString()。所以time O(n),space O(n)。

代码如下:
```java

public String reverseWords(String str) {
        char[] s str.toCharArray();


        if (s == null || s.length() <= 1) {
            return s;
        }

        String[] strs = s.split(" ");
        StringBuilder sb = new StringBuilder();
        for (int i = strs.length - 1; i >= 0; i--) {
            sb.append(strs[i]);
            if (i != 0) {
                sb.append(" ");
            }
        }

        return sb.toString();
    }
```
LC186是输入char[] s返回为void,所以可以inplace的做space O(1)。由于做了上面lintcode的题我第一反应还是把char[]变成String然后根据上面的步骤得到return的String再String.toCharArray(),但是这样做明显复杂了。时间上都是O(n),且要遍历整个char[],所以没法优化了,所有只有优化空间想办法做O(1) space。每个word的长度显然不可能一样,那么左边一个word直接跟右边一个word交换明显太复杂不合适。那么先想到先整体reverse,这样的话每个word的位置已经正确,但是word本身就反过来了,那么再扫一遍把每一个word reverse一遍就可以了。怎么判断每一个word呢?那肯定需要两个指针,i指向word第一个char,j指向word最后一个char,那么j指向一个空格的时候j-1就指向了当前word的最后一个char,再把这个word reverse就好,那么最后一个word后面没有空格,所以扫面完后最后的i,j-1还需要再reverse一下。

代码如下

```java
public String reverseWords(String str) {
        char[] s = str.toCharArray();

        if (s == null || s.length <= 1) {
            return new String(s);
        }

        reverse(s, 0, s.length - 1);
        int i = 0;
        int j = 0;
        while (j < s.length) {
            if (s[j] == ' ') {
                reverse(s, i, j-1);
                i = j+1;
            }
            j++;
        }
        reverse(s, i, j-1);

        return new String(s);
    }

    private void reverse(char[] s, int i, int j) {
        while (i < j) {
            char t = s[i];
            s[i] = s[j];
            s[j] = t;
            i++;
            j--;
        }
    }
```

#套路总结
---
- 程序的模块化很重要,单独把reverse函数提出来就不用在主函数里面重复写多次了。
- 当时间复杂度不再能够被优化的时候,保持相同时间复杂度的情况下可以考虑优化空间。当然,经常也有通过空间换取时间的情况。

#Follow Up
---
- 有leading trailing space, 或者每个word之间不止一个space怎么处理。
  - 我觉得应该跟面试官讨论这种情况,看他想要怎么处理,是我的话我应该会说,ok, let's remove the leading trailing spaces for now,先不考虑它,word之间的spaces的话我reverse过来可不可以只留一个space,那么这样的话我就可以用我的第一种方法解了。

LeetCode 143 Reorder List

#**LeetCode 143**
---
https://leetcode.com/problems/reorder-list/description/

Yifeng Zeng

#题目描述
---
Reorder List

#思路报告
---

我们假定要reorder的list是dummy->1->2->3->4->5->...->n-1->n->Null
最primitive的想法是:
1. 先遍历一边list得到有n个点,先把1拿出来,并且把2记录下来,再从2找到n, 把n放到1后面,得到dummy->1->n->Null
2. 把2拿出来,并把3记录下来,再次3找到n-1,把他们连起来得到dummy->1->n->2->n-1->Null。
3. 重复上述步骤直到中点

这个时间复杂度应该是O(n^2)。那么我们怎么优化呢。

首先,我们找n, n-1, n-2...每一次都是遍历list,所以是O(n^2),那么如果我们有一个list是n->n-1->n-2->...那么我们就可以很方便的找到下一个candidate,所以我们想到了reverse linked list。而我们只需要翻转后半部的linked list,所以我们需要找到中点。找中点的操作我使用最常见的快慢指针,这里我就不介绍了。

代码如下:
```java
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public void reorderList(ListNode head) {
        if (head == null) {
            return;
        }

        // find mid
        ListNode mid = findMid(head);
        // System.out.println(mid.val);

        // reverse
        ListNode tail = reverseList(mid.next);
        // tail will be the start of the second half
        mid.next = null; // actuall we don't need this
        // tail is now the start of the reversed second half
        // print(head);
        // print(tail);

        // now merge two list head & tail
        ListNode dummy = new ListNode(0);
        ListNode cur = dummy;
        while (head != null && tail != null) {
            cur.next = head;
            head = head.next;
            cur = cur.next;
            cur.next = tail;
            tail = tail.next;
            cur = cur.next;
        }
        cur.next = head;

        // return dummy.next;
    }

    private ListNode findMid(ListNode head) {
        ListNode slow = head;
        ListNode fast = head.next;
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
        }
        return slow;
    }

    private ListNode reverseList(ListNode head) {
        ListNode prev = null;
        while (head != null) {
            ListNode next = head.next;
            head.next = prev;
            prev = head;
            head = next;
        }
        return prev;
    }

    private void print(ListNode head) {
        while (head != null) {
            System.out.print(head.val + " ");
            head = head.next;
        }
        System.out.println();
    }
}
```



#套路总结
---
- 程序的模块化很重要,单独把findMid和reverseList函数提出来这样主函数会看起来比较清晰。
- 当找n,n-1,n-2...的时候前面的遍历都是重复的,所以想到反过来能不能行,所以想到了reverse后面一半。

MarkDown demo


>reference: http://www.cnblogs.com/fanzhidongyzby/p/6637084.html
https://zh.wikipedia.org/wiki/Markdown

---------------------------------------

1. 安装Atom

下载安装Atom:https://atom.io/

---

2. 增强预览(markdown-preview-plus)

支持预览实时渲染。(Ctrl + Shift + M)

支持Latex公式。(Ctrl + Shift + X)

\[
e ^ {i\pi} + 1 = 0
\]

e<sup>2</sup>

x<sub>0</sub>

~~Strikethrough~~

(C)Copyright

--

(R)

(TM)

(P)

+-

' '

'' ''

---

3. 同步滚动(markdown-scroll-sync) (好象有问题)

#一级标题

- 一
- 二
  - 2.1
  - 2.2
    - 2.2.1
    - 2.2.2
      - 2.2.2.1
      - 2.2.2.2
- 三



##二级标题 水平分割线

* * *
***
*****
- - -
---------------------------------------
---

###三级标题 强调

*强调(斜体)*
_强调(斜体)_

**加重强调**

又或者以制表符或至少四个空格缩进的行,例如:

    第一行代码
    第二行代码
    第三行代码

####四级标题 引用

> 这一整段的内容都会作为一个HTML的引用元素。
引用元素是会自动优化排版的(reflowable,可回流)。
你可以任意地将引用的内容包含进来,然后所有这些都会
被解析成为单独一个引用元素。

> 这是一个引用。这是第一行
这是第二行。
>> 这是一个嵌套的引用。这是第一行。
这是第二行
>
> 外层引用的第三行。前面需要一个视觉上的空行表示内层嵌套的结束,空行前面的>可以有可以没有。

---

4. 代码增强(language-markdown)
```Java
public String reverseWords(String str) {
        char[] s str.toCharArray();


        if (s == null || s.length() <= 1) {
            return s;
        }

        String[] strs = s.split(" ");
        StringBuilder sb = new StringBuilder();
        for (int i = strs.length - 1; i >= 0; i--) {
            sb.append(strs[i]);
            if (i != 0) {
                sb.append(" ");
            }
        }

        return sb.toString();
    }
```

---

5. 图片粘贴(markdown-image-paste)

截图到剪切板,Ctrl + V就可以直接贴
![](186.png)

---

6. 表格编辑(markdown-table-editor)

| Name   | Age | Weight |
| ------ | --- | ------ |
| Yifeng | 30  | 100    |
|        |     |        |




Tuesday, January 16, 2018

Java中如何遍历Map对象的4种方法.

“Java中如何遍历Map对象的4种方法.” Java中如何遍历Map对象的4种方法 - CSDN博客, blog.csdn.net/tjcyjd/article/details/11111401.

Thursday, November 9, 2017

What are carriage return, linefeed, and form feed?

https://stackoverflow.com/questions/3091524/what-are-carriage-return-linefeed-and-form-feed

“What Are Carriage Return, Linefeed, and Form Feed?” Newline - What Are Carriage Return, Linefeed, and Form Feed? - Stack Overflow, stackoverflow.com/questions/3091524/what-are-carriage-return-linefeed-and-form-feed.

Friday, June 30, 2017

Wednesday, June 14, 2017

Java - why doesn't ArrayList as key in HashMap work?

https://stackoverflow.com/questions/35560067/why-doesnt-arraylist-as-key-in-hashmap-work

“Why Doesn't ArrayList as Key in HashMap Work?” Java - Why Doesn't ArrayList as Key in HashMap Work? - Stack Overflow, stackoverflow.com/questions/35560067/why-doesnt-arraylist-as-key-in-hashmap-work. Accessed 14 June 2017.

Saturday, April 8, 2017

Does Java pass by reference or pass by value?

http://www.javaworld.com/article/2077424/learn-java/does-java-pass-by-reference-or-pass-by-value.html

Sintes, Tony. “Does Java Pass by Reference or Pass by Value?” JavaWorld, JavaWorld, 26 May 2000, www.javaworld.com/article/2077424/learn-java/does-java-pass-by-reference-or-pass-by-value.html. Accessed 8 Apr. 2017.

Tuesday, March 28, 2017

Operation latency

From:
https://fusiontables.google.com/DataSource?snapid=S523155yioc
Latency numbers every programmer should knowJeff Dean (http://research.google.com/people/jeff/)

operation
 
latency (ns)
 
 
L1 cache reference0.5
Branch mispredict5
L2 cache reference7
Mutex lock/unlock25
Main memory reference100
Compress 1K bytes with Zippy3,000
Send 2K bytes over 1 Gbps network20,000
Read 1 MB sequentially from memory250,000
Round trip within same datacenter500,000
Disk seek10,000,000
Read 1 MB sequentially from disk20,000,000
Send packet CA->Netherlands->CA150,000,000

Thursday, March 23, 2017

Set, HashSet, Map, HashMap, TreeSet, TreeMap

https://teamtreehouse.com/community/set-hashset-map-hashmap-treeset-treemap

“Set, HashSet, Map, HashMap, TreeSet, TreeMap.” Set, HashSet, Map, HashMap, TreeSet, TreeMap | Treehouse Community, teamtreehouse.com/community/set-hashset-map-hashmap-treeset-treemap. Accessed 23 Mar. 2017.

Monday, March 20, 2017

Master-Master vs Master-Slave Database Architecture

http://stackoverflow.com/questions/3736969/master-master-vs-master-slave-database-architecture

“Master-Master vs Master-Slave Database Architecture?” Stack Overflow, stackoverflow.com/questions/3736969/master-master-vs-master-slave-database-architecture. Accessed 21 Mar. 2017.

Thursday, March 16, 2017

HashMap vs HashTable

http://stackoverflow.com/questions/40471/differences-between-hashmap-and-hashtable

“Differences between HashMap and Hashtable?” Java - Differences between HashMap and Hashtable? - Stack Overflow, stackoverflow.com/questions/40471/differences-between-hashmap-and-hashtable. Accessed 16 Mar. 2017.