提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
目前大概能写简单或者中等题了,正在追求优解
一、哈希
hash的原理在多线程里有讲,表面是一个连续的数组,在碰到hash冲突的时候会退为链表和红黑树,当一个链表上挂的东西过长的时候就会扩容,hash的初始化和扩容容量和他的概率有关,大概就是每个链表上挂8个的概率很小,所以以这个理由扩容。
hash在leetcode中主要表现为查找,因为一个东西hash后到List中去找到的时间复杂度是O(1),没有链表时就是比较hash值直接查找,有链表时会从头一个个比值,总的来说还是O(1),根据这个原理我认为hash是便于查找,不便于大量数据插入。
题目的范式是hash.containsKey(key)

不理解hash查找之前
java
class Solution {
public int[] twoSum(int[] nums, int target) {
int i=0;
int[] arr=new int[2];
while( i <=nums.length-1){
int temp=target-nums[i];
for(int j=i+1;j<=nums.length-1;j++){
if(nums[j]==temp){
arr[0]=i;
arr[1]=j;
return arr;
}
}
i++;
}
return arr;
}
}
想法基本没有问题,hash之后
java
class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer,Integer> hash=new HashMap<Integer,Integer>();
for(int i=0;i<nums.length;i++){
if(!hash.containsKey(target-nums[i])){
hash.put(nums[i],i);
}else{
return new int[]{hash.get(target-nums[i]),i};
}
}
return new int[0];
}
}
这里外层是一次循环O(n),内层是hashO(1),相乘还是O(n),差距很大了



这题在ai帮助下想到了序列化key,然后hash,然后有点追求速度的想法。慢的原因是用了StringBuffer,这个有锁所以慢,后来用了StringBuilder就快一些。还有一种方法是排序,但是排序可能没有字母表好。
java
class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
List finallist=new ArrayList();
Map<String,List<String>> hash=new HashMap();
for(String word:strs){
int[] wordchar=new int[26];
for(int i=0;i<word.length();i++){
wordchar[word.charAt(i)-'a']++;
}
StringBuffer buffer=new StringBuffer();
for(int i=0;i<26;i++){
buffer.append(wordchar[i]).append(',');
}
if(!hash.containsKey(buffer.toString())){
hash.put(buffer.toString(),new ArrayList<String>());
}
hash.get(buffer.toString()).add(word);
}
finallist.addAll(hash.values());
return finallist;
}
}
java
class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
List<List<String>> finallist=new ArrayList<>();
Map<String,List<String>> hash=new HashMap<>();
for(String word:strs){
int[] wordchar=new int[26];
for(int i=0;i<word.length();i++){
wordchar[word.charAt(i)-'a']++;
}
StringBuilder buffer=new StringBuilder();
for(int i=0;i<26;i++){
buffer.append(wordchar[i]).append(',');
}
if(!hash.containsKey(buffer.toString())){
hash.put(buffer.toString(),new ArrayList<String>());
}
hash.get(buffer.toString()).add(word);
}
finallist.addAll(hash.values());
return finallist;
}
}


这题看了答案,不能有n-1.然后了解到for循环一直没有进去就不算时间复杂度.。除了提前返回,没有任何优化。
java
class Solution {
public int longestConsecutive(int[] nums) {
Set<Integer> hash=new HashSet<Integer>();
for(int n: nums){
hash.add(n);
}
int max=0;
for(int n:nums){
if(!hash.contains(n-1)){
int cur=1;
while(hash.contains(n+1)){
cur++;
n++;
}
if(cur>nums.length/2){
return cur;
}
max=Math.max(max,cur);
}
}
return max;
}
}

二、双指针(未完)
这题想到了多次挪零,也普及了三种双指针:普通、快慢、滑窗。看到考的是双指针,就理所应当想到了将零与末尾元素交换,但是这样又无序了,有点矛盾,只能一个个挪0.

java
class Solution {
public void moveZeroes(int[] nums) {
int l=0,r=0;
for(;r<nums.length;r++){
if(nums[r]!=0){
swap(nums,l,r);
l++;
}
}
}
public void swap(int[] nums,int l,int r){
int tmp;
tmp=nums[l];
nums[l]=nums[r];
nums[r]=tmp;
}
}
了解到下标就是减现有0的个数,但是并没有更快
java
class Solution {
public void moveZeroes(int[] nums) {
int n,count=0;
if(nums.length==1){
return;
}
for(int i=0;i<nums.length;i++){
if(nums[i]!=0 && count==0){
continue;
}
if(nums[i]!=0 ){
nums[i-count]=nums[i];
nums[i]=0;
}else{
count++;
}
}
}
}
方法没问题,问题在于非零元素的两次赋值,既要挪零,又要将非零元素置零
java
class Solution {
public void moveZeroes(int[] nums) {
int cur = 0;
for (int i = 0; i < nums.length; i++) {
if (nums[i] != 0) {
nums[cur] = nums[i];
cur++;
}
}
for (int i = cur; i < nums.length; i++) {
nums[i] = 0;
}
}
}


虽然没有做出来,但是整体结构已经很像了,主要是数学功底不足,证明不出
java
class Solution {
public int maxArea(int[] height) {
int l=0,r=height.length-1;
int tmp=culculate(height,l,r);
while(l<r){
if(l+1<height.length-1 && culculate(height,l,r)<=culculate(height,l+1,r)){
tmp=Math.max(culculate(height,l+1,r),tmp);
}
if(r-1>=0 && culculate(height,l,r)<=culculate(height,l,r-1)){
tmp=Math.max(culculate(height,l,r-1),tmp);
r--;
}
l++;
}
return tmp;
}
public int culculate(int[] height,int l,int r){
int x=r-l;
int ich=Math.min(height[l],height[r]);
return x*ich;
}
}
-----------------------------------------------------------------正解
public class Solution {
public int maxArea(int[] height) {
int l = 0, r = height.length - 1;
int ans = 0;
while (l < r) {
int area = Math.min(height[l], height[r]) * (r - l);
ans = Math.max(ans, area);
if (height[l] <= height[r]) {
++l;
}
else {
--r;
}
}
return ans;
}
}
作者:力扣官方题解
链接:https://leetcode.cn/problems/container-with-most-water/solutions/207215/sheng-zui-duo-shui-de-rong-qi-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
三、写这个的原因
也许对教学以
及初学者有帮助
总结
从最后一次代码来看,我目前的水平还处于if-else的水平,改错方法属于增加if-else限制来补充逻辑不够。匿名函数和新特性都不会,这是需要加强的地方。