Algorithm

DFS & BFS

DFS:Depth First Search,深度优先搜索算法,是一种以stack实现的算法。

BFS:Breath First Search,广度优先搜索算法,是一种以queue实现的算法。

stack和queue的区别:stack是先进后出,queue是先进先出。

假设我们已知一个graph如下:

首先我们使用DFS来遍历整个图

  1. 我们需要把图的数据录入到dict里面

    1
    2
    3
    4
    5
    6
    7
    8
    graphs = {
    'A': ['B', 'C'],
    'B': ['A', 'C', 'D'],
    'C': ['A', 'B', 'D', 'E'],
    'D': ['B', 'C', 'E', 'F'],
    'E': ['C', 'D'],
    'F': ['D']
    }
  2. 规划dfs算法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    def dfs(graph, s):
    """
    we use stack to do dfs
    :param graph: graph data
    :param s: start node
    :return: the dfs data
    """
    stack = [s]
    visited = [s]
    while len(stack) > 0:
    vertex = stack.pop() # 弹出最后一个元素
    nodes = graph[vertex] # 获取相邻的node
    for n in nodes:
    if n not in visited: # 判断该node是否已经遍历过
    stack.append(n) # 如果没有遍历,就添加到stack里面
    if vertex not in visited: # 判断当前vertex是否遍历过
    visited.append(vertex)
    return visited
  3. 运行function

    1
    2
    if __name__ == '__main__':
    print(dfs(graphs, 'A'))

代码解析:

因为stack是先进后出,所以我们手动写一下代码的运行规律

1
2
3
4
5
6
1. 起始点是A, 此时的stack=[B,C], visisted=[A]。按照stack的规律,下一个node是C
2. 起始点C, 此时的stack=[B,D,E], visisted=[A,C]。按照stack的规律,下一个node是E
3. 起始点E, 此时的stack=[B,D], visisted=[A,C,E]。按照stack的规律,下一个node是D
4. 起始点D, 此时的stack=[B,F], visisted=[A,C,E,D]。按照stack的规律,下一个node是F
5. 起始点F, 此时的stack=[B], visisted=[A,C,E,D,F]。按照stack的规律,下一个node是B
6. 起始点B, 此时的stack=[], visisted=[A,C,E,D,F,B]。

所以node的遍历顺序是: [A,C,E,D,F,B]

完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
graphs = {
'A': ['B', 'C'],
'B': ['A', 'C', 'D'],
'C': ['A', 'B', 'D', 'E'],
'D': ['B', 'C', 'E', 'F'],
'E': ['C', 'D'],
'F': ['D']
}


def dfs(graph, s):
"""
we use stack to do dfs
:param graph: graph data
:param s: start node
:return: the dfs data
"""
stack = [s]
visited = [s]
while len(stack) > 0:
vertex = stack.pop() # 弹出最后一个元素
nodes = graph[vertex] # 获取相邻的node
for n in nodes:
if n not in visited: # 判断该node是否已经遍历过
stack.append(n) # 如果没有遍历,就添加到stack里面
if vertex not in visited: # 判断当前vertex是否遍历过
visited.append(vertex)
return visited


if __name__ == '__main__':
print(dfs(graphs, 'A'))

然后我们使用bfs来遍历整个图

Graph的数据一样,所以我们只需要写出相对应的function即可

*queue: *是一种先进先出的数据结构。我们可以看到start node是A:

1
2
3
4
5
6
1. start node是A,此时的queue = [B, C], 此时visited=[A]
2. 按照先进先出的原则,下一下访问的node是B,此时的queue=[C,D](因为A,B都已经被访问过了) 此时visited=[A,B]
3. 下一个被访问的node是C,那么此时的queue=[D,E](A,B已被访问), 此时visited=[A,B,C]
4. 下一个访问的node是D, 此时的queue=[E,F], 此时的visited=[A,B,C,D]
5. 下一个访问的node是E, 此时的queue=[F], 此时的visited=[A,B,C,D, E]
6. 下一个访问的node是F, 此时的queue=[], 此时的visited=[A,B,C,D, E,F]

所以最终的访问顺序为[A,B,C,D,E,F]。具体代码实现如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def bfs(graph, s):
"""
implement the bfs
:param graph: graph data
:param s: start node
:return:
"""
# we use queue in bfs
queue = [s]
visited = [s]
while len(queue) > 0:
vertex = queue.pop(0) # 取出第一个元素
nodes = graph[vertex]
for n in nodes:
if n not in visited:
queue.append(n)
visited.append(n)
return visited

总结

DFS和BFS的主要差别就是stack和queue的使用。

BFS使用场景:bfs主要是运用在寻找最短路径

DFS使用场景:dfs主要是运用在寻找graph中的某一个点

Dijkstra 最短路径算法

Dijkstra最短路径使用priority queue来实现的。

priority queue是queue的一种类型,不同的是pq是根据权重来排序的,比如:

1
queue = [{9, 'A'}, {1, 'B'}]

那么在priority queue里面queue就会变成:

1
[{1, 'B'}, {9, 'A'}]

在Python里面可以使用heapq来实现priority queue:

1
2
3
4
5
6
7
8
9
10
import heapq
pq = []
# 把数据添加到priority queue
heapq.heappush(pq, {0, 'A'})
heapq.heappush(pq, {1, 'B'})
heapq.heappush(pq, {3, 'D'})
heapq.heappush(pq, {2, 'C'})

# 取出数据我们可以使用heappop
heapq.heappop(pq) # 取出的数据是{0, 'A'}

当我们查看pq这个list的时候显示的数据顺序不是根据权重来的,但是当我们使用heapq.heappop(pq)就能得到正确的数据。

在使用Dijkstra算法的时候,graphedge之间是要有权重的,比如:

我们可以把该图的数据按照dict的格式导入到Python:

1
2
3
4
5
6
7
8
graphs = {
'A': {'B': 5, 'C': 1},
'B': {'A': 5, 'C': 2, 'D': 1},
'C': {'A': 1, 'B': 2, 'D': 4, 'E': 8},
'D': {'B': 1, 'C': 4, 'E': 3, 'F': 6},
'E': {'C': 8, 'D': 3},
'F': {'D': 6}
}

算法解析:

假设我们的起始点为A,pq展示的是heapq处理过的数据

1
2
3
4
5
6
1. 起始点A, pq=[{C, 1}(A-C), {B, 5}(A-B)], visited=[A], dist[A] = 0. 下一个node是C
2. 起始点C, pq = [{B,3}(A-C-B), {D, 5}(A-C-D), {B, 5}(A-B), {E, 9}(A-C-E)], visited=[A,C], A-C的距离为1。里面所有点的距离都是A-点的距离(A-C-B的距离是3,所以{B,3})。所以下一个node是{B,3}
3. 起始点B, pq=[{D, 4}(A-C-B-D), {D, 5}(A-C-D), {B, 5}(A-B), {E, 9}(A-C-E)], visited=[A,C,B], A-B的距离3, dist[B]=3. 所以下一个node是{D,4}
4. 起始点D, pq[{E, 7}(A-C-B-D-E), {D, 5}(A-C-D), {B, 5}(A-B), {F, 10}(A-C-B-D-F), {E, 9}(A-C-E)], visited=[A,C,B,D], A-D的距离4, dist[D]=4. 所以下一个node是E.
4. 起始点E, pq[{B, 5}(A-B), {F, 10}(A-C-B-D-F), {E, 9}(A-C-E)], visited=[A,C,B,D,E], A-E的距离7, dist[E]=7. 所以下一个node是F, 因为别的node都被访问过了.
5. 起始点F, pq[], visited=[A,C,B,D,E,F], A-F的距离10, dist[F]=10.

所以遍历的顺序为: [A,C,B,D,E,F](可以理解为[A,C,B,D,E][A,C,B,D,F])

具体代码实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
"""
Dijkstra 最短路径算法
使用priority queue的数据结构来完整该算法,根据每一个node的priority来实现的
谁的priority大,谁在前面。
Python有priority queue可以直接使用
"""

import heapq
import math

graphs = {
'A': {'B': 5, 'C': 1},
'B': {'A': 5, 'C': 2, 'D': 1},
'C': {'A': 1, 'B': 2, 'D': 4, 'E': 8},
'D': {'B': 1, 'C': 4, 'E': 3, 'F': 6},
'E': {'C': 8, 'D': 3},
'F': {'D': 6}
}


def init_distance(graph, s):
"""
init the distance for every vertex
:param graph:
:param s:
:return:
"""
distance = {s: 0}
for vertex in graph:
if vertex != s:
distance[vertex] = math.inf
return distance


def dijkstra(graph, s):
"""
find the shortest way
:param graph: graph data
:param s: start node
:return:
"""
pq = []
visited = set()
parent = {s: None}
distance = init_distance(graph, s)
heapq.heappush(pq, (0, s))

while len(pq) > 0:
pair = heapq.heappop(pq)
# because the data is lik: (0,A)
# so we need to get two args
dist = pair[0]
vertex = pair[1]
visited.add(vertex)
# get the closed vertex
nodes = graph[vertex].keys()
for node in nodes:
if node not in visited:
total_dist = dist + graph[vertex][node] # calculate the distance from A
if total_dist < distance[node]:
heapq.heappush(pq, (total_dist, node))
parent[node] = vertex
distance[node] = total_dist

return distance, parent


if __name__ == '__main__':
print(dijkstra(graphs, 'A'))

LinkList algorithm

首先定义一个List Node的class:

1
2
3
4
class ListNode:
def __init__(self, x):
self.val = x
self.next = None

常见问题

  1. 如何找到链表的中间元素?

    可以采用快慢指针的原理,第一个指针向后走一步,第二个指针向后走两步,这样第二个指针结束的时候第一个指针刚好到中间

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    def find_mid(head):
    """
    找到该list中间的元素
    :param head: the head of list
    :return:
    """
    slow = head
    fast = head

    while fast.next is not None and fast.next.next is not None:
    slow = slow.next
    fast = fast.next.next

    return slow

    使用递归的思想来解决这个问题,在递归的时候我们已经可以得到相对应的长度,可以找到中点位置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    def find_mid_recursion(node, index):
    """
    find the mid by recursion
    :param node:
    :param index:
    :return:
    """
    global mid
    if node.next is not None:
    find_mid_recursion(node.next, index+1)
    else:
    mid = int(index / 2)

    if mid == index:
    return node

    return None
  2. 判断链表是否有环

    也可以通过使用快慢指针的思想来解决这个问题。当慢指针和快指针重合的时候代表着有环(但是容易进入死循环)。比如1->2->3->1,这样就是一个简单的环,当slow指向2的时候fast也指向2,所以表示有环

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    def check_cycle(node):
    """
    check whether exist cycle in the linklist
    :param node:
    :return:
    """
    slow = node
    fast = node

    while fast.next is not None and fast.next.next is not None:
    slow = slow.next
    fast = fast.next.next

    if slow == fast:
    return True

    return False
  3. 反转链表

    使用recursion来实现反表。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    def reverse_recursion(curr, next):
    """
    reverse the link list by recursion
    :param curr:
    :param next:
    :return:
    """
    if next is None:
    return
    reverse_recursion(next, next.next)
    next.next = curr
    curr.next = None

    不用递归的实现方法。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    def reverse(node):
    """
    reverse the link list without recursion
    :param node:
    :return:
    """
    curr = node
    next = node.next
    curr.next = None

    while next is not None:
    temp = next.next
    next.next = curr

    curr = next
    next = temp
  4. 删除经过排序的链表中重复的节点。

    判断当前数字是否和下一个相等,如果相等,记录该node,继续循环,找到与改数字不相同的数字,然后把curr.next = 该不相同node

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    def find_diff(node):
    """
    in a sort link list, remove the duplicate value
    :param node:
    :return:
    """
    curr = node
    record = None

    while curr.next is not None:
    next_node = curr.next
    if curr.val == next_node.val and record is None:
    record = curr
    elif curr.val != next_node.val and record is not None:
    record.next = next_node
    record = None

    curr = curr.next
  5. 计算两个链表数字之和

    将链表代表的数字进行相加即可,注意首位代表的是个位。3->1->5 代表513,5->9->2 代表295,最终计算结果为 8->0->8, 808。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    def sum_list(l1, l2):
    """
    add two link list together
    将链表代表的数字进行相加即可,注意首位代表的是个位。3->1->5 代表513,5->9->2 代表295,最终计算结果为 8->0->8, 808。
    :param l1:
    :param l2:
    :return:
    """
    over_ten = False
    s = ListNode(0)
    head = s

    while l1 is not None or l1 is not None:
    v1 = l1.val if l1 is not None else 0
    v2 = l2.val if l2 is not None else 0

    sum_value = v1 + v2
    sum_value = sum_value + 1 if over_ten else sum_value

    if sum_value >= 10:
    over_ten = True
    sum_value = sum_value % 10

    s.val = sum_value

    l1 = l1.next if l1 is not None else None
    l2 = l2.next if l2 is not None else None

    if l1 is None and l2 is None:
    break
    else:
    s.next = ListNode(0)
    s = s.next

    return head
  6. 链表-奇数位升序偶数位降序-让链表变成升序

    先拆分链表,然后把偶数链表翻转,然后合并

    比如list为:1 10 2 9 3 8 4 7 5 6

    奇数链表为:1 2 3 4 5

    偶数链表为:10 9 8 7 6

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    def merge_two_list(l):
    """
    split to two list
    :param l:
    :return:
    """
    odd = ListNode(0)
    even = ListNode(0)

    odd_head = odd
    even_head = even

    index = 1
    while l is not None:
    if index % 2 != 0:
    odd.val = l.val
    odd.next = ListNode(None)
    odd = odd.next
    else:
    even.val = l.val
    even.next = ListNode(None)
    even = even.next

    l = l.next

    odd = None
    even = None

    reverse_recursion(odd_head, odd_head.next)
    reverse_recursion(even_head, even_head.next)

    # merge them together

    最后这个部分由于处理不太得当,所以写起来有点麻烦,先搁置一下

  7. 一个单向链表,删除倒数第N个数据。

    首先准备两个指针,第一个指针先走n个,然后第二个出发,当第一个指针为None时,第二个指针刚好指向该数据

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    def delete_n_element(l, n):
    """
    删除倒数n的element
    :param l:
    :param n:
    :return:
    """
    index = 0
    curr = l
    corr = l

    while curr is not None:
    if index >= n + 1:
    corr = corr.next
    curr = curr.next
    index += 1

    print(corr.val)

KMP string match

Worst case: $O(m+n)$

Two stages:

  • Pre-processing: table building O(m)
  • Matching: O(n)

Space complexity: O(m)

*首先需要制作一个prefix table: *

这个是根据字符串的前后字符有一个相等的, i-len

这样的话我们的prefix就制作好了-1,0,0,1,2.

然后我们需要根据这个table来进行KMP的search的算法:

具体的实现代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
package KMP;

import java.util.Arrays;

public class KMP {

public int[] prefix(String str) {
int[] prefix = new int[str.length()];

// 左右最长公共后缀, 左右两边肯定相等的
prefix[0] = 0;
int len = 0;
int i = 1;

while (i < str.length()) {
if (str.charAt(i) == str.charAt(len)) {
len ++;
prefix[i] = len;
i ++;
} else {
if (len > 0) {
len = prefix[len - 1];
} else {
prefix[i] = len;
i ++;
}
}
}
move(prefix);
return prefix;
}

public void move(int[] prefix) {
if (prefix.length - 1 >= 0) System.arraycopy(prefix, 0, prefix, 1, prefix.length - 1);
prefix[0] = -1;
}

public void kmp_search (String text, String match) {
int[] prefix = prefix(match);
System.out.println(Arrays.toString(prefix));

// text lens n index i
// prefix len m index j
int i = 0;
int j = 0;
while ( i < text.length()) {
if (j == match.length() - 1 && text.charAt(i) == match.charAt(j)) {
System.out.println(text.substring(i - j, i));
j = prefix[j];
}
if (text.charAt(i) == match.charAt(j)) {
i ++;
j ++;
} else {
j = prefix[j];
if (j == -1) {
j ++;
i ++;
}
}
}
}

public static void main(String[] args) {
String str = "ababcabaa";
String text = "abababcabaaabababababa";
KMP kmp = new KMP();
kmp.kmp_search(text, str);
}
}

录制了一个短视频来了解一下:

Tree

昨天顺便看了一下关于tree的一些常用算法,给大家看一下。

首先tree要有一个node:

1
2
3
4
5
6
7
8
package tree;

public class Node {
int val;
Node left;
Node right;
Node(int x) {this.val = x;}
}

然后是对tree的一些常用操作的代码,都是使用递归来完成的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
package tree;
import tree.Node;

public class Example {

/**
* 平衡二叉树,左字树和右子树高度相同
*
* @param root
* @param x
* @return
*/
public boolean search(Node root, int x) {
if (root == null) return false;
if (root.val == x) return true;

if (x < root.val) return search(root.left, x);
else return search(root.right, x);
}

public void preorder(Node root) {
if (root == null) return;
System.out.print(root.val);
preorder(root.left);
preorder(root.right);
}

/**
* 在BST里面使用inorder是输出排序过的结果
* @param root node
*/
public void inorder(Node root) {
if (root == null) return;
inorder(root.left);
System.out.print(root.val);
inorder(root.right);
}

public void postorder(Node root) {
if (root == null) return;
postorder(root.left);
postorder(root.right);
System.out.print(root.val);
}


public Node create(int[] nums) {
Node root = null;

for (int x : nums) root = insert(root, x);

return root;
}

public Node insert(Node root, int val) {
if (root == null) return new Node(val);

if (val <= root.val) {
root.left = insert(root.left, val);
} else {
root.right = insert(root.right, val);
}

return root;
}

/**
* 104
* 求最大深度的算法
* @param root Node
* @return
*/
public int tree_max(Node root) {
if (root == null) return Integer.MIN_VALUE;

int max_left = tree_max(root.left);
int max_right = tree_max(root.right);

return Math.max(root.val, Math.max(max_left, max_right));
}

/**
* 求最小深度的算法 111
* @param root Node
* @return min depth
*/
public int MinDepth(Node root) {
if (root == null) return 0;
if (root.left == null && root.right == null) return 1;

int left = MinDepth(root.left);
int right = MinDepth(root.right);

if (root.left == null) return right + 1;
if (root.right == null) return left + 1;

return Math.min(left, right) + 1;
}

/**
* 查看该tree是否有加和等于该sum的数据 112
* @param root
* @param sum
* @return
*/
public boolean PathSum(Node root, int sum) {
if (root == null) return false;
if (root.left == null && root.right == null) return root.val == sum;

boolean left = PathSum(root.left, sum - root.val);
boolean right = PathSum(root.right, sum - root.val);

return left | right;
}

// 下面是关于两个node的解决方法

/**
* func solve(p, q):
* if not q and not p return ...
* if f(p,q) return ....
* c1 = solve(p.child, q.child)
* c2 = solve(p.child, q.child)
* return g(p, q, c1, c2)
*/

/**
* 100
* 判断两个树是不是相等
* @param t1 Node
* @param t2 Node
* @return boolean
*/
public boolean SameTree(Node t1, Node t2) {
if (t1 == null && t2 == null) return true;
if (t1 == null || t2 == null) return false;

boolean left = SameTree(t1.left, t2.left);
boolean right = SameTree(t1.right, t2.right);

return t1.val == t2.val && (left && right);
}

/**
* 101
* 判断两个树是不是镜像,和上面的问题刚好相反
* @param t1 Node
* @param t2 Node
* @return boolean
*/
public boolean mirror(Node t1, Node t2) {
if (t1 == null && t2 == null) return true;
if (t1 == null || t2 == null) return false;

boolean left = mirror(t1.left, t2.right);
boolean right = mirror(t1.right, t2.left);

return t1.val == t2.val && (left && right);
}


public static void main(String[] args) {
Example e = new Example();
int[] nums = new int[] {5,3,1,4,7,6};
Node root = e.create(nums);
// Node root = new Node(5);
// Node left = new Node(3);
// Node right = new Node(7);
// root.left = left;
// root.right = right;
//
// left.left = new Node(1);
// left.right = new Node(4);
//
// right.left = new Node(6);
e.preorder(root);
System.out.println();

e.inorder(root);
System.out.println();

e.postorder(root);
System.out.println();

System.out.println(e.MinDepth(root));
}

}

回溯算法

可以理解为一个决策树的遍历过程,我们只需要考虑:路径,选择列表,结束条件。 伪代码如下:

1
2
3
4
5
6
7
8
9
10
result = []
def backtrack(path, select_list):
if condition:
result.add(path)
return

for list in select_list:
make a select
backtrack(path, select_list)
drawback select

核心在for里面的循环,递归之前调用make a select,递归之后drawback select

比如LeetCode里面的 *46. Permutations * 一个排列组合的问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;


public class Permutations {
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> res = new LinkedList<>();

back_track(res, new ArrayList<>(), nums);
return res;
}


public void back_track(List<List<Integer>> res, List<Integer> temp, int[] nums) {
if (temp.size() == nums.length) {
res.add(new ArrayList<>(temp));
return;
}

for (int i = 0; i < nums.length; i ++) {
// 避免重复项
if (temp.contains(nums[i])) continue;
temp.add(nums[i]);
back_track(res, temp, nums);
temp.remove(temp.size() - 1);
}
}

public static void main(String[] args) {
int[] nums = new int[] {1,2,3};

Permutations p = new Permutations();
List<List<Integer>> res = p.permute(nums);

for (List<Integer> l : res) {
System.out.println(Arrays.toString(l.toArray()));
}
}
}
----- End Thanks for reading-----