[leetcode]2.Add_Two_numbers

Problem

You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list.

You may assume the two numbers do not contain any leading zero, except the number 0 itself.

Example

1
2
3
Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8
Explanation: 342 + 465 = 807.

Solution

Intuition

Keep track of the carry using a variable and simulate digits-by-digits sum starting from the head of list, which contains the least-significant digit.
LinkList
LinkList
Figure 1. Visualization of the addition of two numbers: 342 + 465 = 807342+465=807.
Each node contains a single digit and the digits are stored in reverse order.

Algorithm

Just like how you would sum two numbers on a piece of paper, we begin by summing the least-significant digits, which is the head of l1l1 and l2l2. Since each digit is in the range of 0 \ldots 90…9, summing two digits may “overflow”. For example 5 + 7 = 125+7=12. In this case, we set the current digit to 22 and bring over the carry = 1carry=1 to the next iteration. carrycarry must be either 00 or 11 because the largest possible sum of two digits (including the carry) is 9 + 9 + 1 = 199+9+1=19.

The pseudocode is as following:

Initialize current node to dummy head of the returning list.
Initialize carry to 00.
Initialize pp and qq to head of l1l1 and l2l2 respectively.
Loop through lists l1l1 and l2l2 until you reach both ends.
Set xx to node pp’s value. If pp has reached the end of l1l1, set to 00.
Set yy to node qq’s value. If qq has reached the end of l2l2, set to 00.
Set sum = x + y + carrysum=x+y+carry.
Update carry = sum / 10carry=sum/10.
Create a new node with the digit value of (sum \bmod 10)(summod10) and set it to current node’s next, then advance current node to next.
Advance both pp and qq.
Check if carry = 1carry=1, if so append a new node with digit 11 to the returning list.
Return dummy head’s next node.
Note that we use a dummy head to simplify the code. Without a dummy head, you would have to write extra conditional statements to initialize the head’s value.

Take extra caution of the following cases:

Test case Explanation
l1=[0,1]l1=[0,1]
l2=[0,1,2]l2=[0,1,2] When one list is longer than the other.
l1=[]l1=[]
l2=[0,1]l2=[0,1] When one list is null, which means an empty list.
l1=[9,9]l1=[9,9]
l2=[1]l2=[1] The sum could have an extra carry of one at the end, which is easy to forget.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode dummyHead = new ListNode(0);
ListNode p = l1, q = l2, curr = dummyHead;
int carry = 0;
while (p != null || q != null) {
int x = (p != null) ? p.val : 0;
int y = (q != null) ? q.val : 0;
int sum = carry + x + y;
carry = sum / 10;
curr.next = new ListNode(sum % 10);
curr = curr.next;
if (p != null) p = p.next;
if (q != null) q = q.next;
}
if (carry > 0) {
curr.next = new ListNode(carry);
}
return dummyHead.next;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution:
# @return a ListNode
def addTwoNumbers(self, l1, l2):
carry = 0
root = n = ListNode(0)
while l1 or l2 or carry:
v1 = v2 = 0
if l1:
v1 = l1.val
l1 = l1.next
if l2:
v2 = l2.val
l2 = l2.next
carry, val = divmod(v1+v2+carry, 10)
n.next = ListNode(val)
n = n.next
return root.next

Complexity Analysis

Time complexity : O(\max(m, n))O(max(m,n)). Assume that mm and nn represents the length of l1l1 and l2l2 respectively, the algorithm above iterates at most \max(m, n)max(m,n) times.

Space complexity : O(\max(m, n))O(max(m,n)). The length of the new list is at most \max(m,n) + 1max(m,n)+1.

Follow up

What if the the digits in the linked list are stored in non-reversed order? For example:

(3 \to 4 \to 2) + (4 \to 6 \to 5) = 8 \to 0 \to 7 (3→4→2)+(4→6→5)=8→0→7

[leetcode]1.Two_Sum

Problem

problem

Given an array of integers, return indices of the two numbers such that they add up to a specific target.

You may assume that each input would have exactly one solution, and you may not use the same element twice.

1
2
3
4
5
Example:
Given nums = [2, 7, 11, 15], target = 9,

Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].

Solution

Approach #1

The brute force approach is simple. Loop through each element xx and find if there is another value that equals to target - xtarget−x.

1
2
3
4
5
6
7
8
9
10
public int[] twoSum(int[] nums, int target) {
for (int i = 0; i < nums.length; i++) {
for (int j = i + 1; j < nums.length; j++) {
if (nums[j] == target - nums[i]) {
return new int[] { i, j };
}
}
}
throw new IllegalArgumentException("No two sum solution");
}

Complexity Analysis

Time complexity : O(n^2). For each element, we try to find its complement by looping through the rest of array which takes O(n) time. Therefore, the time complexity is O(n^2)

Space complexity : O(1).

Approach #2 (Two-pass Hash Table) [Accepted]

To improve our run time complexity, we need a more efficient way to check if the complement exists in the array. If the complement exists, we need to look up its index. What is the best way to maintain a mapping of each element in the array to its index? A hash table.

We reduce the look up time from O(n) to O(1) by trading space for speed. A hash table is built exactly for this purpose, it supports fast look up in near constant time. I say “near” because if a collision occurred, a look up could degenerate to O(n) time. But look up in hash table should be amortized O(1) time as long as the hash function was chosen carefully.

A simple implementation uses two iterations. In the first iteration, we add each element’s value and its index to the table. Then, in the second iteration we check if each element’s complement (target - nums[i]target−nums[i]) exists in the table. Beware that the complement must not be nums[i]nums[i] itself!

1
2
3
4
5
6
7
8
9
10
11
12
13
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
map.put(nums[i], i);
}
for (int i = 0; i < nums.length; i++) {
int complement = target - nums[i];
if (map.containsKey(complement) && map.get(complement) != i) {
return new int[] { i, map.get(complement) };
}
}
throw new IllegalArgumentException("No two sum solution");
}

Complexity Analysis:

Time complexity : O(n). We traverse the list containing nn elements exactly twice. Since the hash table reduces the look up time to O(1), the time complexity is O(n).

Space complexity : O(n). The extra space required depends on the number of items stored in the hash table, which stores exactly nn elements.

Approach #3 (One-pass Hash Table) [Accepted]

It turns out we can do it in one-pass. While we iterate and inserting elements into the table, we also look back to check if current element’s complement already exists in the table. If it exists, we have found a solution and return immediately.

1
2
3
4
5
6
7
8
9
10
11
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
int complement = target - nums[i];
if (map.containsKey(complement)) {
return new int[] { map.get(complement), i };
}
map.put(nums[i], i);
}
throw new IllegalArgumentException("No two sum solution");
}
1
2
3
4
5
6
7
hash_tbl={}
for i in range(len(nums)):
c=target-nums[i]
if c in hash_tbl:
return [hash_tbl[c],i]
else:
hash_tbl[nums[i]]=i

Complexity Analysis:

Time complexity : O(n). We traverse the list containing nn elements only once. Each look up in the table costs only O(1) time.

Space complexity : O(n). The extra space required depends on the number of items stored in the hash table, which stores at most nn elements.

showoff presenter

Showoff Presenter

github website

Executing code live on your slides

If you mark a code block with the execute keyword, then it will have a small play icon on the lower right. When the indicator is pressed Showoff can run the code live and display the results in a slide-down console window over your slides. If you are using the Presenter window, the output will be displayed on the Display window.

ruby

install

howto
Step One— Install Ruby with RVM
Before we do anything else, we should run a quick update to make sure that all of the packages we download to our VPS are up to date:

sudo apt-get update
Once that’s done, we can start installing RVM, Ruby Version Manager. This is a great program that lets you use several versions of Ruby on one server; however, in this case, we will just use it to install the latest version of Ruby on the droplet.

If you do not have curl on your system, you can start by installing it:

sudo apt-get install curl
To install RVM, open terminal and type in this command:

\curl -L https://get.rvm.io | bash -s stable
After it is done installing, load RVM. You may first need to exit out of your shell session and start up a new one.

source ~/.rvm/scripts/rvm
In order to work, RVM has some of its own dependancies that need to be installed. To automatically install them:

rvm requirements
You may need to enter your root password to allow the installation of these dependencies.

On occasion the zlib package may be reported as missing. The RVM page describes the issue and the solution in greater detail here.
In some rare cases it might be required to install packages via rvm pkg, if unsure try installing ruby first.

RVM can install required packages automatically via autolibs:

rvm autolibs rvm_pkg
This will tell RVM to install the missing dependencies, RVM will try to detect what is missing using pkg-config, as not all packages provide it please do not be surprised RVM will insist on installing readline - even it was installed.

Step Two—Install Ruby
Once you are using RVM, installing Ruby is easy.

rvm install ruby
The latest ruby is now installed. However, since we accessed it through a program that has a variety of Ruby versions, we need to tell the system to use the version we just installed by default.

rvm use ruby –default
Step Three—Install RubyGems
The next step makes sure that we have all the required components of Ruby on Rails. We can continue to use RVM to install gems; type this line into terminal.

rvm rubygems current
Step Four—Install Rails
Once everything is set up, it is time to install Rails. To start, open terminal and type in:

gem install rails
This process may take a while, be patient with it. Once it finishes you will have Ruby on Rails installed on your droplet.

See More
Once you have installed Ruby on Rails on your server, you can proceed to Create a SSL Certificate for your site or Install an FTP server

docker 入门

what is docker

引用官网的话:

Docker is the world’s leading software containerization platform
PACKAGE YOUR APPLICATION INTO A STANDARDIZED UNIT FOR SOFTWARE DEVELOPMENT
Docker containers wrap a piece of software in a complete filesystem that contains everything needed to run: code, runtime, system tools, system libraries – anything that can be installed on a server. This guarantees that the software will always run the same, regardless of its environment.
可以把他想象成一个用了一种新颖方式实现的超轻量虚拟机,在大概效果上也是正确的。当然在实现的原理和应用上还是和VM有巨大差别的,并且专业的叫法是应用容器(Application Container)。
为啥要用容器?

那么应用容器长什么样子呢,一个做好的应用容器长得就好像一个装好了一组特定应用的虚拟机一样。比如我现在想用MySQL那我就找个装好MySQL的容器,运行起来,那么我就可以使用 MySQL了。

那么我直接装个 MySQL不就好了,何必还需要这个容器这么诡异的概念?话是这么说,可是你要真装MySQL的话可能要再装一堆依赖库,根据你的操作系统平台和版本进行设置,有时候还要从源代码编译报出一堆莫名其妙的错误,可不是这么好装。而且万一你机器挂了,所有的东西都要重新来,可能还要把配置在重新弄一遍。但是有了容器,你就相当于有了一个可以运行起来的虚拟机,只要你能运行容器,MySQL的配置就全省了。而且一旦你想换台机器,直接把这个容器端起来,再放到另一个机器就好了。硬件,操作系统,运行环境什么的都不需要考虑了。

在公司中的一个很大的用途就是可以保证线下的开发环境、测试环境和线上的生产环境一致。当年在 Baidu 经常碰到这样的事情,开发把东西做好了给测试去测,一般会给一坨代码和一个介绍上线步骤的上线单。结果代码在测试机跑不起来,开发就跑来跑去看问题,一会儿啊这个配置文件忘了提交了,一会儿啊这个上线命令写错了。找到了一个 bug 提上去,开发一看,啊我怎么又忘了把这个命令写在上线单上了。类似的事情在上线的时候还会发生,变成啊你这个软件的版本和我机器上的不一样……在 Amazon 的时候,由于一个开发直接担任上述三个职位,而且有一套自动化部署的机制所以问题会少一点,但是上线的时候大家还是胆战心惊。

若果利用容器的话,那么开发直接在容器里开发,提测的时候把整个容器给测试,测好了把改动改在容器里再上线就好了。通过容器,整个开发、测试和生产环境可以保持高度的一致。

此外容器也和VM一样具有着一定的隔离性,各个容器之间的数据和内存空间相互隔离,可以保证一定的安全性。

那为啥不用VM?

那么既然容器和 VM 这么类似为啥不直接用 VM 还要整出个容器这么个概念来呢?Docker 容器相对于 VM 有以下几个优点:

启动速度快,容器通常在一秒内可以启动,而 VM 通常要更久
资源利用率高,一台普通 PC 可以跑上千个容器,你跑上千个 VM 试试
性能开销小, VM 通常需要额外的 CPU 和内存来完成 OS 的功能,这一部分占据了额外的资源

为啥相似的功能在性能上会有如此巨大的差距呢,其实这和他们的设计的理念是相关的。 VM 的设计图如下:
VM
VM 的 Hypervisor 需要实现对硬件的虚拟化,并且还要搭载自己的操作系统,自然在启动速度和资源利用率以及性能上有比较大的开销。而 Docker 的设计图是这样的:
Docker
Docker 几乎就没有什么虚拟化的东西,并且直接复用了 Host 主机的 OS,在 Docker Engine 层面实现了调度和隔离重量一下子就降低了好几个档次。 Docker 的容器利用了 LXC,管理利用了 namespaces 来做权限的控制和隔离, cgroups 来进行资源的配置,并且还通过 aufs 来进一步提高文件系统的资源利用率。

其中的 aufs 是个很有意思的东西,是 UnionFS 的一种。他的思想和 git 有些类似,可以把对文件系统的改动当成一次 commit 一层层的叠加。这样的话多个容器之间就可以共享他们的文件系统层次,每个容器下面都是共享的文件系统层次,上面再是各自对文件系统改动的层次,这样的话极大的节省了对存储的需求,并且也能加速容器的启动。

下一步

有了前面的这些介绍,应该对 Docker 到底是啥有些了解了吧, Docker 是 用 Go 语言编写的,源代码托管在 github 而且居然只有 1W 行就完成了这些功能。如果想尝试一下的话可以看 官方介绍了,应该上手会容易一些了。博主也是新手,如有错误欢迎拍砖指正。

参看史上最全Docker资料集粹
Docker,从这里做起!
Docker的英文本意是“搬运工”,在程序员的世界里,Docker搬运的是集装箱(Container),集装箱里装的是任意类型的App,开发者通过Docker可以将App变成一种标准化的、可移植的、自管理的组件,可以在任何主流系统中开发、调试和运行。最重要的是,它不依赖于任何语言、框架或系统。
不久前Docker 1.0的发布,意味着Docker自身已经转变为一个分发应用的开放平台。如今的Docker已经备受青睐,云服务提供商,包括微软、 IBM 、 Rackspace 、 Google 以及其他主要的 Linux 提供商如 Canonical 和 Red Hat ,都已经开始支持 Docker 。
本专题精选Docker入门文章,以及大牛们的PPT分享给大家。更多精彩请关注CSDN Docker技术社区(http://docker.csdn.net/)。
同时欢迎加入CSDN Docker技术群(QQ群号:303806405),一起探讨Docker之道!(我会告诉你群里有官方镜像的临时解决方案吗!)
To be a Docker,从这里开始!

安装

ubuntu下安装步骤

  • Update your APT package index.

    1
    $ sudo apt-get update
  • Install Docker.

    1
    $ sudo apt-get install docker-engine
  • Start the docker daemon.

    1
    $ sudo service docker start
  • Verify docker is installed correctly.

    1
    $ sudo docker run hello-world

This command downloads a test image and runs it in a container. When the container runs, it prints an informational message. Then, it exits.

Docker实践指南

Jquery 常用技巧

Jquery的checkbox,radio,select等方法总结

Haorooms

Jquery通过Ajax方式来提交Form表单

1
2
3
4
5
6
7
8
$.ajax({
type: "POST",
url: "some.php",
data: "name=John&location=Boston",
success: function(msg){
alert( "Data Saved: " + msg );
}
});

但是对于form的每个input都写的话,是不是要吐血?
看看我的方法,首先我们把所有的input的name和value都取下来

1
2
3
4
5
6
7
8
9
10
11
$.ajax({
var str_data=$("#dlg_form input").map(function(){
return ($(this).attr("name")+'='+$(this).val());
}).get().join("&") ;
type: "POST",
url: "some.php",
data: str_data,
success: function(msg){
alert( "Data Saved: " + msg );
}
});

linux下web开发

配置

  • 路径
    如果网站地址为:~/webapp,那么首先你要在/var/www/下建立链接:
    1
    ln -s ~/webapp /var/www/

注意这里target必须为绝对路径,否则有可能链接失效

  • 权限,设置文件夹权限,否则可能链接在这里,但是访问不到
    1
    sudo chmod 777 webapp为/ -R

服务器

  • 重启.

    1
    sudo /etc/init.d/apache2 restart

    问题解决

    • 500 错误

使用APACHE+PHP时,通过URL浏览网站时可能会提示HTTP 500错误,这使得新手无从下手,因为看不到具体的错误信息。及时查看APACHE的ERROR LOG也只是记录了一条500错误信息而已。
要解决问题首先要知道问题所在,所以必须知道更详细的问题描述才行。其实只需要配置php.ini(/etc/php5/apache2/)即可。在php的安装目录中找到php.ini文件并打开,找到display_errors,默认情况下是display_errors = Off,把Off修改为On,保存关闭文件,然后重启apache。
这样如果编写的脚本再有错误浏览器就会显示出来这些错误了,知道错误所在那就看你的了:)

  • codeignitor在linux下大小写敏感造成的问题
    controllers/welcome.php 首字母大写会出出问题,显示404 Page Not Found