def intersection(nums1,nums2): record1 = set() for i in range(len(nums1)): record1.add(nums1[i]) res = set() for i in range(len(nums2)): if nums2[i] in record1: res.add(nums2[i]) return res
s ='aabbccdd' d ={} for item in s: d[item]=d.get(item,0)+1 print(d)
""" {'a': 2, 'b': 2, 'c': 2, 'd': 2} """
pop(key)方法:删除一个key,对应的value也会从dict中删除
1 2 3 4
>>> d.pop('Bob') 75 >>> d {'Michael': 95, 'Tracy': 85}
LeetCode 350 Intersection of Two Arrays
给定两个数组nums,求两个数组的交集。
——如nums1=[1,2,2,1],nums2=[2,2]
——结果为[2,2]
——出现的顺序可以是任意的
解题:
使用dict,遍历nums1,将nums1的字符作为key,出现频率作为value。
遍历nums2,如果在dict有nums2的字符,将其加入res中,该字符对应的value减1
1 2 3 4 5 6 7 8 9 10 11
def subString(nums1,nums2): dict1 ={} res = [] for i in range(len(nums1)): dict1[nums1[i]]=dict1.get(nums1[i],0)+1 for i in range(len(nums2)): if dict1[nums2[i]]>0: res.append(nums2[i]) dict1[nums2[i]]-=1 return res
classSolution: defisAnagram(self, s: str, t: str) -> bool: record = {} record2 = {} for i inrange(len(s)): record[s[i]] = record.get(s[i],0)+1 for i inrange(len(t)): record2[t[i]] = record2.get(t[i],0)+1 return record2 == record
defhappyNumber(num): record = set() while num notin record:#如果num不在set中进行循环操作;若在set中证明进入死循环,不符合题目要求 record.add(num) #记录每次操作的num squareSum = 0#每次的和是要重新计算的 #把一个数字的所有位数取出,并进行操作 while num>0: remain = num%10 squareSum += remain*remain num = num//10 if squareSum ==1: returnTrue else: num = squareSum returnFalse
deflengthOfLongestSubstring(s): ifnot s: return0 i,j = 0,-1 s = list(s) visited = [] res = 1#字符串不为空时,至少有1个 while i<len(s): if j+1<len(s) and s[j+1] notin visited: j+=1 visited.append(s[j]) else: #在visited有这个元素 visited.pop(0) #删除左边元素 i +=1 #结果的保存和更新 iflen(visited)>1: # res = max(res,len(visited)) res = max(res,j-i+1) return res
class Solution: def minSubArrayLen(self, s: int, nums: List[int]) -> int: i,j = 0,-1 #注意j从-1开始 sum = 0 #初始时sum为0 res = len(s)+1 #初始设置为不可能取到的一个最大值 #窗口滑动的过程,只要左边界不越界就能滑动下去 while i<len(nums): if sum<s and j+1<len(s):#j+1不能越界 j+=1 #j向前滑动,并将所指元素纳入子数组中 sum+=nums[j] else: #sum>=s,先移除i所指元素,i向前移动 sum-=nums[i] i+=1 #经过一系列操作后,满足条件的子数组出现了 #此时存储当前满足条件的子数组的结果 if sum >= s: res = min(res,j-l+1) #注意:遍历一遍没有解的情况 if res == len(nums): return0 return res
4,在while循环中,如果arr[i]<v,则与(arr[lt+1…i)==v数组左边界的)arr[lt+1]进行交换,由于换过来的元素等于v,因此i直接向前移动;(且arr[l+1…lt] <v 的数组范围扩容)lt+1对应的是 <v 的元素因此lt需要向前移动一个位置。如果arr[i]>v, 则直接与arr[gt-1]进行交换,此时gt-1对应的是 >v 的元素,因此gt需要向前移动一位,但是由于交换过来的元素是未知的所以 i 不能向前移动。如果arr[i] == v 则 i 直接向前移动。
因为i是紧挨左边界的所以左边界交换来的元素已知,而右边界交换来的元素未知。
5,最后进行arr[l]与(arr[l+1…lt]<v的右边界)arr[lt]的交换。
6,最后进行sort(arr, l, lt-1)和sort(arr, gt, r)的递归调用。
1
LeetCode真题—75.Sort Colors
Sort Colors
Medium
Given an array with n objects colored red, white or blue, sort them in-place so that objects of the same color are adjacent, with the colors in the order red, white and blue.
Here, we will use the integers 0, 1, and 2 to represent the color red, white, and blue respectively.
Note: You are not suppose to use the library’s sort function for this problem.
MaxHeap<Integer> maxHeap = new MaxHeap<Integer>(100); int N = 100; // 堆中元素个数 int M = 100; // 堆中元素取值范围[0, M) for( int i = 0 ; i < N ; i ++ ) maxHeap.insert( new Integer((int)(Math.random() * M)) );
Integer[] arr = new Integer[N]; // 将maxheap中的数据逐渐使用extractMax取出来 // 取出来的顺序应该是按照从大到小的顺序取出来的 for( int i = 0 ; i < N ; i ++ ){ arr[i] = maxHeap.extractMax(); System.out.print(arr[i] + " "); } System.out.println();
// 确保arr数组是从大到小排列的 for( int i = 1 ; i < N ; i ++ ) assert arr[i-1] >= arr[i]; }
private int n; // 节点数 private int m; // 边数 private boolean directed; // 是否为有向图 private boolean[][] g; // 图的具体数据
// 构造函数 public DenseGraph( int n , boolean directed ){ assert n >= 0; this.n = n; this.m = 0; // 初始化没有任何边 this.directed = directed; // g初始化为n*n的布尔矩阵, 每一个g[i][j]均为false, 表示没有任和边 // false为boolean型变量的默认值 g = new boolean[n][n]; }
public int V(){// 返回节点个数 return n; } public int E(){ // 返回边的个数 return m; }
// 向图中顶点v和顶点v之间添加一条边 public void addEdge( int v , int w ){ //先判断是否越界 assert v >= 0 && v < n ; assert w >= 0 && w < n ; //如果v,w之间已经有边了,则直接返回 if( hasEdge( v , w ) ) return;
private int n; // 节点数 private int m; // 边数 private boolean directed; // 是否为有向图 private Vector<Integer>[] g; // 图的具体数据
// 构造函数 public SparseGraph( int n , boolean directed ){ assert n >= 0; this.n = n; this.m = 0; // 初始化没有任何边 this.directed = directed; // g初始化为n个空的vector, 表示每一个g[i]都为空, 即没有任和边 g = (Vector<Integer>[])new Vector[n]; //g的每一个元素g[i]也都是一个Vector for(int i = 0 ; i < n ; i ++) g[i] = new Vector<Integer>(); }
public int V(){ return n;} // 返回节点个数 public int E(){ return m;} // 返回边的个数
// 向图中添加一个边 public void addEdge( int v, int w ){
assert v >= 0 && v < n ; assert w >= 0 && w < n ;
g[v].add(w); if( v != w && !directed ) g[w].add(v);
m ++; }
// 验证图中是否有从v到w的边 boolean hasEdge( int v , int w ){
assert v >= 0 && v < n ; assert w >= 0 && w < n ; //g[v]是一个Vector,循环g[v]查看其中是否含有w for( int i = 0 ; i < g[v].size() ; i ++ ) if( g[v].elementAt(i) == w ) return true; return false; } }
// 返回图中一个顶点的所有邻边 // 由于java使用引用机制,返回一个Vector不会带来额外开销, public Iterable<Integer> adj(int v) { //定义一个可迭代方法,求v节点的临边所对应节点 assert v >= 0 && v < n; Vector<Integer> adjV = new Vector<Integer>(); for(int i = 0 ; i < n ; i ++ ) //遍历v节点所在的那一行 if( g[v][i] ) //如果为true证明有临边 adjV.add(i); //将临边对应的节点存入vector return adjV; //返回vector }
2、邻接链表的迭代方法实现:
这里的g是Vector类型变量,里面存储的元素就是临边所对应的节点。
1 2 3 4 5 6
// 返回图中一个顶点的所有邻边 // 由于java使用引用机制,返回一个Vector不会带来额外开销, public Iterable<Integer> adj(int v){ assert v >= 0 && v < n; return g[v]; }
图的算法框架
1、首先建立Graph的接口
1 2 3 4 5 6 7 8 9 10
// 图的接口 public interface Graph {
public int V(); //返回节点个数 public int E(); //返回边的个数 public void addEdge( int v , int w ); // 向图中添加一个边 boolean hasEdge( int v , int w ); // 验证图中是否有从v到w的边 void show(); // 显示图的信息 public Iterable<Integer> adj(int v); // 返回图中一个顶点的所有邻边(所对应节点) }
// 稀疏图 - 邻接表 import java.util.Vector; public class SparseGraph implements Graph {
private int n; // 节点数 private int m; // 边数 private boolean directed; // 是否为有向图 private Vector<Integer>[] g; // 图的具体数据
// 构造函数 public SparseGraph( int n , boolean directed ){ assert n >= 0; this.n = n; this.m = 0; // 初始化没有任何边 this.directed = directed; // g初始化为n个空的vector, 表示每一个g[i]都为空, 即没有任和边 g = (Vector<Integer>[])new Vector[n]; for(int i = 0 ; i < n ; i ++) g[i] = new Vector<Integer>(); }
public int V(){ return n;} // 返回节点个数 public int E(){ return m;} // 返回边的个数
// 向图中添加一个边 public void addEdge( int v, int w ){
assert v >= 0 && v < n ; assert w >= 0 && w < n ;
g[v].add(w); if( v != w && !directed ) g[w].add(v);
m ++; }
// 验证图中是否有从v到w的边 public boolean hasEdge( int v , int w ){
assert v >= 0 && v < n ; assert w >= 0 && w < n ;
for( int i = 0 ; i < g[v].size() ; i ++ ) if( g[v].elementAt(i) == w ) return true; return false; }
// 显示图的信息 public void show(){
for( int i = 0 ; i < n ; i ++ ){ System.out.print("vertex " + i + ":\t"); for( int j = 0 ; j < g[i].size() ; j ++ ) System.out.print(g[i].elementAt(j) + "\t"); System.out.println(); } }
// 返回图中一个顶点的所有邻边 // 由于java使用引用机制,返回一个Vector不会带来额外开销, public Iterable<Integer> adj(int v) { assert v >= 0 && v < n; return g[v]; } }
public ReadGraph(Graph graph, String filename){// //定义类型为Graph(向上转型),使得在这个模板中既可以传入稀疏图又可以传入稠密图。 readFile(filename); //读取文件
try { int V = scanner.nextInt(); //读取文本文件第一行第一个元素(代表节点个数) if (V < 0) throw new IllegalArgumentException("number of vertices in a Graph must be nonnegative"); assert V == graph.V(); //判断读取文件的节点数和图中的节点数是一致的
int E = scanner.nextInt(); //读取文本文件第一行第二个元素(代表临边个数) if (E < 0) throw new IllegalArgumentException("number of edges in a Graph must be nonnegative");
for (int i = 0; i < E; i++) { int v = scanner.nextInt(); //读取第二行第一个元素(代表节点) int w = scanner.nextInt(); //读取第二行第二个元素(代表节点) assert v >= 0 && v < V; assert w >= 0 && w < V; //在这两个节点之间加一条临边,调用的是传进来的graph所对应子类的addEdge方法。 graph.addEdge(v, w); } } catch (InputMismatchException e) { String token = scanner.next(); throw new InputMismatchException("attempts to read an 'int' value from input stream, but the next token is \"" + token + "\""); } catch (NoSuchElementException e) { throw new NoSuchElementException("attemps to read an 'int' value from input stream, but there are no more tokens available"); } }
private void readFile(String filename){ //定义读取文件的方法 assert filename != null; try { File file = new File(filename); if (file.exists()) { //如果该文件存在 FileInputStream fis = new FileInputStream(file); scanner = new Scanner(new BufferedInputStream(fis), "UTF-8"); scanner.useLocale(Locale.ENGLISH); } else throw new IllegalArgumentException(filename + "doesn't exist."); } catch (IOException ioe) { //无法打开该文件 throw new IllegalArgumentException("Could not open " + filename, ioe); } } }
// 构造函数, 求出无权图的联通分量。 public Components(Graph graph){
// 算法初始化 G = graph; visited = new boolean[G.V()]; //根据图中节点数量给visited开空间 id = new int[G.V()]; ccount = 0; for( int i = 0 ; i < G.V() ; i ++ ){ //通过循环初始化visited,将每个元素都设为false visited[i] = false; id[i] = -1; }
// 求图的联通分量 for( int i = 0 ; i < G.V() ; i ++ ) // if( !visited[i] ){ //如果该节点没有被访问过(visited[i]为false) dfs(i); //dfs()它可以将i和与i相连接的所有节点遍历一遍,没遍历的节点一定在另外的一个联通分量中 ccount ++; } }
// 返回图的联通分量个数 int count(){ return ccount; }
// 查询点v和点w是否联通 boolean isConnected( int v , int w ){ assert v >= 0 && v < G.V(); assert w >= 0 && w < G.V(); return id[v] == id[w]; } }
Stack<Integer> s = new Stack<Integer>(); // 通过from数组逆向查找到从s到w的路径, 存放到栈中 int p = w; //设置指针p指向当前节点w while( p != -1 ){ //不是起始节点。因为起始节点的前一个节点是-1,而当p==-1时,证明起始节点已经压入栈中,则退出循环 s.push(p); //将当前节点压入栈中 p = from[p]; //指针p指向当前节点的前一个节点 }
// 从栈中依次取出元素, 获得顺序的从s到w的路径 Vector<Integer> res = new Vector<Integer>(); while( !s.empty() ) //只要栈不为空,则出栈 res.add( s.pop() );
return res; }
// 打印出从s点到w点的路径 void showPath(int w){
assert hasPath(w) ;
Vector<Integer> vec = path(w); for( int i = 0 ; i < vec.size() ; i ++ ){ // System.out.print(vec.elementAt(i)); if( i == vec.size() - 1 ) //遍历到了最后一个节点 System.out.println(); else System.out.print(" -> "); } } }
// 构造函数, 寻路算法, 寻找图graph从s点到其他点的路径 public ShortestPath(Graph graph, int s){
// 算法初始化 G = graph; assert s >= 0 && s < G.V();
visited = new boolean[G.V()]; //是否已经遍历 from = new int[G.V()]; ord = new int[G.V()]; for( int i = 0 ; i < G.V() ; i ++ ){ visited[i] = false; from[i] = -1; ord[i] = -1; } this.s = s;
// 无向图最短路径算法, 从s开始广度优先遍历整张图 Queue<Integer> q = new LinkedList<Integer>();