数据结构串讲
作者:互联网
本篇属于数据结构串讲内容。讲真,一说数学我就头大,一看LeetCode就头疼。
一 hash
Given two strings s and t , write a function to determine if t is an anagram of s.
Example 1:
Input: s = "anagram", t = "nagaram"
Output: true
Example 2:Input: s = "rat", t = "car"
Output: false
Note:
You may assume the string contains only lowercase alphabets.Follow up:
What if the inputs contain unicode characters? How would you adapt your solution to such case?
如果是Python,一行代码哈:Python 得用字典是hash
return sorted(s) == sorted(t)
Java吧。如果想到一种排序策略,再去比较。
//数组
public boolean isAnagram(String s, String t) {
if(s.trim().equals(t.trim().trim())){
return true;
}
char[] sChars = s.toCharArray();
char[] tChars = t.toCharArray();
Arrays.sort(sChars);
Arrays.sort(tChars);
return Arrays.equals(sChars, tChars);
}
排序嘛。时间复杂度:NlogN.
还可以用hash表:我就用hashmap替代了。
public static boolean isAnagram(String s, String t) {
if(s.trim().equals(t.trim().trim())){
return true;
}
Map<Character,Integer> m1 = new HashMap<>();
Map<Character,Integer> m2 = new HashMap<>();
for(Character c:s.toCharArray()){
m1.put(c, m1.getOrDefault(c, 0) + 1);
}
for(Character c:t.toCharArray()){
m2.put(c, m2.getOrDefault(c, 0) + 1);
}
return m1.equals(m2);
}
理论上这个快N嘛,实际上慢多了。哪些1ms的大佬有更好的方法。
15 threeSum
Given an array nums of n integers, are there elements a, b, c in nums such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
Notice that the solution set must not contain duplicate triplets.
Example 1:
Input: nums = [-1,0,1,2,-1,-4]
Output: [[-1,-1,2],[-1,0,1]]
Example 2:Input: nums = []
Output: []
Example 3:Input: nums = [0]
Output: []
最暴力的解法:N^3,这个题目要注意的是:结果不能有重复的。
使用hashmap: 时间复杂度降到N^2.
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> reslist = new ArrayList<List<Integer>>();
if (nums.length < 3) return reslist;
Set result = new HashSet();
//先排序
Arrays.sort(nums);
Integer t;
Map<Integer,Integer> map = new HashMap<>();
for(int k=0;k<nums.length;k++ ){
map.put(nums[k],k);
}
for(int i=0;i< nums.length;i++){
if(i>0&& nums[i] == nums[i-1]){
continue;
}
for(int j=i+1;j< nums.length;j++){
if(j > i+1 && nums[j] == nums[j-1]){
continue;
}
if((t = map.get(0-nums[i]-nums[j])) != null){
if(t > j){
result.add(new ArrayList<>(Arrays.asList(nums[i], nums[j], nums[t])));
}
else{
break;
}
}
}
}
return new ArrayList<>(result);
}
上面使用hashmap这不是最优解,最优解是两指针从头尾往中间夹的方式。我是不会做的,大神们的这种思路也是看半天才理解。
反反复复看题解,最终击败百分之五
先排序,如果我们第一个数然后去找其他两个数(把这两个数之和看做是一个数),那么问题就变成在有序数组中从[i+1, len-1]这个范围内找到一个符合要求的数,那么就变成了双指针问题。
而是两个边界left和right的和,》0则right 移动,《0则left移动。正好就是所求的解之一。继续寻找其他解,知道双指针相遇。代码不贴了。
小结
hash结构就是对于查找起到O(1)作用。
二 树
98. Validate Binary Search Tree
Given the root of a binary tree, determine if it is a valid binary search tree (BST).
A valid BST is defined as follows:
The left subtree of a node contains only nodes with keys less than the node's key.
The right subtree of a node contains only nodes with keys greater than the node's key.
Both the left and right subtrees must also be binary search trees.Input: root = [2,1,3] Output: true
树:常见的就是遍历,这个很适合用递归。基本思路是找到递归的条件。
这个就是如果违反规则,左侧比中间小,中间比右侧小就是false,否则都递归遍历完左右子树后就是true。时间复杂度O(N)
public boolean isValidBST(TreeNode root) {
return validate(root,Long.MIN_VALUE,Long.MAX_VALUE);
}
public boolean validate(TreeNode node,long min, long max) {
if(node == null){
return true;
}
if(node.val<=min|| node.val>=max){
return false;
}
return validate(node.left,min,node.val )&& validate(node.right,node.val,max);
}
代码为啥要用Long而不是Integer,因为边界条件会卡住。
常见遍历策略:广度优先、深度优先
Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.
Example 1:
Input: n = 3
Output: ["((()))","(()())","(())()","()(())","()()()"]
Example 2:Input: n = 1
Output: ["()"]
Constraints:
1 <= n <= 8
先画做括号,也是采用深度优先遍历策略。
List<String> result = new ArrayList<>();
public List<String> generateParenthesis(int n) {
String res= "";
dfs(n,n,res);
return result;
}
private void dfs(int left, int right, String res) {
//返回条件
if(left<0|| right<0|| left>right){
return;
}
//rule
if(left==0&& right==0){
result.add(res);
return;
}
dfs(left-1, right, res+"(") ;
dfs(left, right-1, res+")") ;
}
堆
堆的操作:插入、删除
Given a non-empty array of integers, return the k most frequent elements.
Example 1:
Input: nums = [1,1,1,2,2,3], k = 2
Output: [1,2]
Example 2:Input: nums = [1], k = 1
Output: [1]
Note:You may assume k is always valid, 1 ≤ k ≤ number of unique elements.
Your algorithm's time complexity must be better than O(n log n), where n is the array's size.
It's guaranteed that the answer is unique, in other words the set of the top k frequent elements is unique.
You can return the answer in any order.
经典top k问题。使用hashmap计数:再取前topk 是个比较容易想到的思路。 使用优先级队列自定义堆。
public int[] topKFrequent(int[] nums, int k) {
int[] reslut = new int[k];
//coner case
if(nums == null|| nums.length==0){
return nums;
}
//遍历
Map<Integer,Integer> map = new HashMap<Integer,Integer>();
for(int i=0; i<nums.length;i++ ){
if(map.containsKey(nums[i]) ){
map.put(nums[i], map.get(nums[i])+1 );
}else{
map.put(nums[i], 1);
}
}
PriorityQueue<Map.Entry<Integer, Integer>> pq =
new PriorityQueue<>((a,b)->(b.getValue()-a.getValue() ) );
//保存到queue
for( Map.Entry<Integer,Integer> entry : map.entrySet() ){
pq.add( entry);
}
//输出结果
for (int i = 0; i < k; i++) {
reslut[i]=pq.poll().getKey();
}
return reslut;
}
时间复杂度:O(Nlogk)
标签:node,return,串讲,nums,int,Output,new,数据结构 来源: https://blog.csdn.net/bohu83/article/details/113881701