3月快刷了一半的题想起来应该记录一下…前几天有用JAVA写的有用C++写的,但后面没有标注的都是用Python写的。
小白一枚,有不对的或者需要改进的地方恳请各位大佬批评指正!

文章目录

  • 2020年三月的每日一题
    • 1号——225. 用队列实现栈
    • 2号——206. 反转链表
    • 3号——面试题 10.01. 合并排序的数组
    • 4号 ——994. 腐烂的橘子
    • 5号——1103. 分糖果 II
    • 6号——面试题57 - II. 和为s的连续正数序列
    • 7号——面试题59 - II. 队列的最大值
    • 8号——322. 零钱兑换
    • 9号——121. 买卖股票的最佳时机
      • 同类型的问题:股票问题
    • 10号——543. 二叉树的直径
    • 11号——1013. 将数组分成和相等的三个部分
    • 12号——1071. 字符串的最大公因子
    • 13号——169. 多数元素
    • 14号——300. 最长上升子序列
    • 15号——695. 岛屿的最大面积
      • 同类型的题目:1034. 边框着色
    • 16号——面试题 01.06. 字符串压缩
    • 17号——1160. 拼写单词
    • 18号——836. 矩形重叠
    • 19号——409. 最长回文串
    • 20号——面试题40. 最小的k个数
    • 21号——365. 水壶问题
    • 22号——945. 使数组唯一的最小增量
    • 23号——876. 链表的中间结点
    • 24号——面试题 17.16. 按摩师
      • 相关问题:leetcode动态规划问题
    • 25号——892. 三维形体的表面积
    • 26号——999. 车的可用捕获量
    • 27号——914. 卡牌分组
    • 28号——820. 单词的压缩编码
      • 相关问题:前缀树(Trie)
    • 29号——1162. 地图分析
    • 30号——面试题62. 圆圈中最后剩下的数字
    • 31号——912. 排序数组
      • 相关问题:几种要会书写的排序方法

2020年三月的每日一题

1号——225. 用队列实现栈

常规操作,模版题
1.Python版本

class MyStack:def __init__(self):"""Initialize your data structure here."""self.queue=collections.deque()def push(self, x: int) -> None:"""Push element x onto stack."""self.queue.append(x)length=len(self.queue)while length>1:self.queue.append(self.queue.popleft())length-=1def pop(self) -> int:"""Removes the element on top of the stack and returns that element."""return self.queue.popleft()def top(self) -> int:"""Get the top element."""return self.queue[0]def empty(self) -> bool:"""Returns whether the stack is empty."""return not bool(self.queue)# Your MyStack object will be instantiated and called as such:
# obj = MyStack()
# obj.push(x)
# param_2 = obj.pop()
# param_3 = obj.top()
# param_4 = obj.empty()

C++版本

class MyStack {private:queue<int> q;
public:/** Initialize your data structure here. */MyStack() {        }    /** Push element x onto stack. */void push(int x) {int size=q.size();q.push(x);while(size--){int temp=q.front();q.pop();q.push(temp);}}   /** Removes the element on top of the stack and returns that element. */int pop() {int topEle=q.front();q.pop();return topEle;}  /** Get the top element. */int top() {return q.front();}   /** Returns whether the stack is empty. */bool empty() {return q.empty();}
};

2号——206. 反转链表

Java版本

/*** Definition for singly-linked list.* public class ListNode {*     int val;*     ListNode next;*     ListNode(int x) { val = x; }* }*/
class Solution {public ListNode reverseList(ListNode head) {if (head == null || head.next == null) return head;ListNode p = reverseList(head.next);head.next.next = head;head.next = null;return p;}
}

3号——面试题 10.01. 合并排序的数组

从后往前进行,比较AB两个数组,那个大放进去哪个。
最后要考虑,如果最后只剩下B,则把B完全放到A的前面。
Python版本

class Solution:def merge(self, A: List[int], m: int, B: List[int], n: int) -> None:"""Do not return anything, modify A in-place instead."""size=len(A)-1n-=1m-=1while(size and n>-1 and m>-1):if A[m]>=B[n]:A[size]=A[m]m-=1else:A[size]=B[n]n-=1size-=1if n>-1:for j in range(0,n+1):A[j]=B[j]j+=1

4号 ——994. 腐烂的橘子

这是一道BFS模版题。

Python版本:
广度优先搜索算法

class Solution:def orangesRotting(self, grid: List[List[int]]) -> int:row=len(grid)line=len(grid[0])time=0direction=[(0,1),(1,0),(0,-1),(-1,0)]queue=collections.deque()fresh=0for i in range(row):for j in range(line):if grid[i][j]==2:queue.append((i,j,0))elif grid[i][j]==1:fresh+=1while queue:i,j,time=queue.popleft()for di,dj in direction:if 0<=i+di<row and 0<=j+dj<line and grid[i+di][j+dj]==1:grid[i+di][j+dj]=2fresh-=1queue.append((i+di,j+dj,time+1))if fresh>0:return -1else:return time

C++版本:

//C++
class Solution {public int orangesRotting(int[][] grid) {int[] dr=new int[]{-1,0,1,0};int[] dc=new int[]{0,-1,0,1};int R=grid.length; //行数int C=grid[0].length; //列数int code=0;Queue<Integer> queue=new ArrayDeque();Map<Integer,Integer> depth=new HashMap();for(int r=0;r<R;++r){for(int c=0;c<C;++c){if(grid[r][c]==2){//找出腐烂的橙子code=r*C+c;//获得橙子在数组中的位置queue.add(code);//放入队列depth.put(code,0);//将此时所有腐烂的橙子的时间节点记为0}}}int alltime=0;while(!queue.isEmpty()){ //开始进行BFScode=queue.remove();int r=code/C;int c=code%C;for(int k=0;k<4;++k){int nr=r+dr[k];int nc=c+dc[k]; if(0<=nr&&nr<R&&0<=nc&&nc<C&&grid[nr][nc]==1){ //对左下右上几个方向进行判断grid[nr][nc]=2;int ncode=nr*C+nc;queue.add(ncode); //将新变成的腐烂的橘子入队列depth.put(ncode,depth.get(code)+1);alltime=depth.get(ncode);}}}for(int[]row:grid)for(int v:row)if(v==1)return -1;return alltime;}
}


学会的知识点:
1.Queue queue=new ArrayDeque();——ArrayDeque
队列的:

栈:
(参考:https://www.cnblogs.com/loveLands/articles/9708717.html)

2.Map<Integer,Integer> depth=new HashMap();——Map map = new HashMap():
其实就是一个键值对接口。
函数原型为:Map<String, Object> map = new HashMap<String, Object>();
在这个声明中,map就是一个容器,主要调用put()、get()方法;

例如:map.put(“user”, obj);
obj是之前声明的一个类的对象,比如为user1,那么就是把user这个对象放到了map容器中了,其中user只是对象的代号,在调用的时候取出,代码为map.get(user);
参数是前面写的代号,得到的是user1这个对象。

HashMap就是一个散列表,它是通过“拉链法”解决哈希冲突。
(参考:https://blog.csdn.net/Dreamlzd/article/details/77827058)

5号——1103. 分糖果 II

题目:

解题:

class Solution {public:vector<int> distributeCandies(int candies, int num_people) {vector<int> ans(num_people,0);int i = 0;while (candies != 0) {ans[i % num_people] += min(candies, i + 1);candies -= min(candies, i + 1);++i;}return ans;}
};

学习点:
对于一个需要循环操作的数组:
ans[i % num_people] += min(candies, i + 1); //数组中i % num_people这个写的方法很巧妙。

6号——面试题57 - II. 和为s的连续正数序列

C++版本

class Solution {public:vector<vector<int>> findContinuousSequence(int target) {vector<vector<int>> result;vector<int> line;int sum=0;int count=(target-1)/2; //等效于target/2取下整int i,j;for(i=1;i<=count;i++){for(j=i;;j++){sum+=j;if(sum==target){line.clear();for(int k=i;k<=j;k++)line.emplace_back(k); //存放和为目标值的这几个数result.emplace_back(line); //存放这个数组sum=0;break;} if(sum>target){sum=0;break;}}}return result;}
};

7号——面试题59 - II. 队列的最大值


C++算法

class MaxQueue {private:queue<int> q; //用来记录插入的值deque<int> max;//用来维护最大值
public:MaxQueue() {}   int max_value() {if(max.empty()) return -1;return max.front();}void push_back(int value) {while(!max.empty()&&value>max.back()){max.pop_back();      }max.push_back(value);q.push(value);}int pop_front() {if(q.empty()) return -1;int num=q.front();if(num==max.front())max.pop_front();q.pop();return num;}
};/*** Your MaxQueue object will be instantiated and called as such:* MaxQueue* obj = new MaxQueue();* int param_1 = obj->max_value();* obj->push_back(value);* int param_3 = obj->pop_front();*/

8号——322. 零钱兑换

大佬总结,模版,常看常背默https://leetcode-cn.com/problems/coin-change/solution/dong-tai-gui-hua-tao-lu-xiang-jie-by-wei-lai-bu-ke/

常规的动态解题方法:

class Solution {vector<int> count;int dp(vector<int>& coins,int amount){if(amount<0) return -1;if(amount==0) return 0;if(count[amount-1]!=0) return count[amount-1];int Min=INT_MAX;for(int coin:coins){int res=dp(coins,amount-coin);if(res>=0&&res<Min)Min=res+1;}count[amount-1]=Min==INT_MAX?-1:Min;return count[amount-1];       }public:int coinChange(vector<int>& coins, int amount) {if(amount<1) return 0;count.resize(amount);//设置count大小return dp(coins,amount);}
};

可以看到解题效率并不高

方法二:贪心+dfs思路:

void coinChange(vector<int>& coins, int amount, int c_index, int count, int& ans)
{if (amount == 0){ans = min(ans, count);return;}if (c_index == coins.size()) return;for (int k = amount / coins[c_index]; k >= 0 && k + count < ans; k--){coinChange(coins, amount - k * coins[c_index], c_index + 1, count + k, ans);}
}int coinChange(vector<int>& coins, int amount)
{if (amount == 0) return 0;sort(coins.rbegin(), coins.rend()); //反向迭代器,从大到小排序int ans = INT_MAX;coinChange(coins, amount, 0, 0, ans);return ans == INT_MAX ? -1 : ans;
}

9号——121. 买卖股票的最佳时机

C++解法

class Solution {public:int maxProfit(vector<int>& prices) {/* int last = 0, profit = 0;for (int i = 0; i < (int)prices.size() - 1; ++i) {last = max(0, last + prices[i+1] - prices[i]);profit = max(profit, last);}return profit;*/int dp_i_0=0,dp_i_1=INT_MIN;for(int i=0;i<prices.size();i++){dp_i_0=max(dp_i_0,dp_i_1+prices[i]);dp_i_1=max(dp_i_1,-prices[i]);}return dp_i_0;}};

同类型的问题:股票问题

这是一连串的dp模版题,其他同样的买股票问题我单写了一篇:
https://blog.csdn.net/chuxuezheerer/article/details/104848202

10号——543. 二叉树的直径

其实就是求左右子树的最大深度。
C++:

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/
class Solution {int res=1;int depth(TreeNode* root){if(root==NULL) return 0;int left=depth(root->left);int right=depth(root->right);      res=max(res,left+right+1);return max(left,right)+1;}public:int diameterOfBinaryTree(TreeNode* root) {depth(root);return res-1;}
};

11号——1013. 将数组分成和相等的三个部分


C++

class Solution {public:bool canThreePartsEqualSum(vector<int>& A) {int sum=accumulate(A.begin(),A.end(),0);if(sum%3!=0) return false;//首先要求数组长度必须是3的倍数才能分成三堆int target=sum/3;int i=0;int length=A.size();int res=0;while(i<length){res=res+A[i];if(res==target)break;i++;            }if (res!=target) return false;int j=i+1;while(j<length-1){res+=A[j];if(res==2*target)return true;j++;}return false;}
};

12号——1071. 字符串的最大公因子

C++

class Solution {bool check(string t,string str){int lens=(int)str.length()/(int)t.length();string res="";for(int i=1;i<=lens;i++)res+=t;return res==str;}public:string gcdOfStrings(string str1, string str2) {int len1=(int)str1.length();int len2=(int)str2.length();string T=str1.substr(0,__gcd(len1,len2));if(check(T,str1)&&check(T,str2)) return T;return "";                }
};

13号——169. 多数元素


这道题最简单的是一种数学方法叫摩尔投票法。
方法二是常规的哈希方法。

class Solution:def majorityElement(self, nums: List[int]) -> int:s=len(nums)count=0for i in range(s):if count==0:target=nums[i]if nums[i]==target:count+=1else:count-=1return target# 方法二:
#        count=len(nums)//2
#       dict={}
#        for num in nums:
#            if num in dict:
#                dict[num]+=1#            else:
#                dict[num]=1#           if dict[num]>count:
#                    return num;

14号——300. 最长上升子序列

class Solution:def lengthOfLIS(self, nums: List[int]) -> int:dp=[0]*len(nums) #从小到大存放nums数组res=0for num in nums:i,j=0,reswhile i<j:mid=(i+j)//2 #其实相当于在dp数组查找中运用二分法if dp[mid]<num :i=mid+1else:j=middp[i]=num if j==res:res+=1return res

方法二,相当于存放每个数组的逆序数

class Solution:def lengthOfLIS(self, nums: List[int]) -> int:if not nums: return 0dp = [1] * len(nums)for i in range(len(nums)):for j in range(i):if nums[j] < nums[i]: dp[i] = max(dp[i], dp[j] + 1)return max(dp)

15号——695. 岛屿的最大面积

方法一:深度优先遍历BFS

#Python3
class Solution:def maxAreaOfIsland(self, grid: List[List[int]]) -> int:m=len(grid)if m==0:return 0n=len(grid[0])def dfs(i,j):if i<0 or i>=m or j<0 or j>=n:return 0;if grid[i][j]==0:return 0grid[i][j]=0top=dfs(i,j-1)bottom=dfs(i,j+1)left=dfs(i-1,j)right=dfs(i+1,j)res=1+sum([top,bottom,left,right])return resans=0for i in range(m):for j in range(n):ans=max(ans,dfs(i,j))return ans

可以看到这个算法时间和空间的需求都蛮大的:

方法二:用广度优先遍历

#Python
class Solution:def maxAreaOfIsland(self, grid: List[List[int]]) -> int:row=len(grid)line=len(grid[0])#官网答案写法:#for i, l in enumerate(grid):#enumerate()函数:讲一个可遍历的数据对象组合成一个索引序列,同时列出数据和数据下标。#for j, n in enumerate(l):res=0for i in range(row):for j in range(line):queue=collections.deque([(i,j)])cur=0while queue:cur_i,cur_j=queue.popleft()if cur_i<0 or cur_j<0 or cur_i>=row or cur_j>=line or grid[cur_i][cur_j]!=1:continuecur+=1grid[cur_i][cur_j]=0for di,dj in [[1,0],[0,1],[0,-1],[-1,0]]:next_i=cur_i+dinext_j=cur_j+djqueue.append((next_i,next_j))res=max(res,cur)return res

其实就是把递归用一个队列来进行维护,

同类型的题目:1034. 边框着色

注意是求连通的边界值!

class Solution:def colorBorder(self, grid: List[List[int]], r0: int, c0: int, color: int) -> List[List[int]]:if not grid or len(grid[0])==0:return gridrow=len(grid)line=len(grid[0])queue=collections.deque([(r0,c0)])visit={(r0,c0)} #记录被访问的位置res=grid[r0][c0] #记录最开始的颜色while queue:i,j=queue.popleft()for di,dj in [[0,1],[-1,0],[0,-1],[1,0]]:cur_i=i+dicur_j=j+djif (cur_i,cur_j) in visit:continue #如果已经被访问过,则跳过后面步骤if cur_i<0 or cur_j<0 or cur_i>=row or cur_j>=line or grid[cur_i][cur_j]!=res:grid[i][j]=color #边界判断,如果为边界值,则原i,j位置的color变elif 0<=cur_i<row and 0<=cur_j<line and grid[cur_i][cur_j]==res:queue.append((cur_i,cur_j))visit.add((cur_i,cur_j))     #将连通的值入栈,入访问序列  return grid

16号——面试题 01.06. 字符串压缩

class Solution:def compressString(self, S: str) -> str:if not S:return Sch=S[0]res=''count=0for num in S:if num==ch:count+=1else:res+=ch+str(count)count=1ch=numres+=ch+str(count)return res if len(res)<len(S) else S

17号——1160. 拼写单词


在Python中用一个字典统计,遍历每一个单词,如果这个单词每个字母对应的数量小于整个字典统计每个字母的数量,则可以构成这个单词。

class Solution:def countCharacters(self, words: List[str], chars: str) -> int:char_count=collections.Counter(chars)res=0for word in words:word_count=collections.Counter(word)if all(word_count[i]<=char_count[i] for i in word_count):res+=len(word)return res

18号——836. 矩形重叠


这种空间问题转换为对横纵坐标的操作。

class Solution:def isRectangleOverlap(self, rec1: List[int], rec2: List[int]) -> bool:x_left=max(rec1[0],rec2[0])x_right=min(rec1[2],rec2[2])y_top=min(rec1[3],rec2[3])y_bottom=max(rec1[1],rec2[1])#右边最小的>左边最大的,则横坐标交叉;#上边最小的>下边最大的,则纵坐标交叉if x_right-x_left>0 and y_top-y_bottom>0:return Trueelse:return False

19号——409. 最长回文串


还是要考虑数学特性,所有数量为偶数的可以直接要,数量为奇数的,可以-1变成偶数加入,最后结果如果原来含有奇数要在+1,因为可以以中心为原点形成对称。

class Solution:def longestPalindrome(self, s: str) -> int:length=len(s)num=collections.Counter(s)res=0max_odd=0for key in num:if(num[key]%2==0):res+=num[key]else:res+=num[key]-1return res if length==res else res+1

20号——面试题40. 最小的k个数


如果不考虑用Python原函数直接排序(如果面试中用的话会被打死吧~~~),就用堆排序或者快排
快排思想排序:

class Solution:def getLeastNumbers(self, arr: List[int], k: int) -> List[int]:length=len(arr)if k<=0 or k>length:return list()left,right=0,length-1while left<right:res=self.partition(arr,left,right)if res==k-1:returnelif res<k-1:res=self.partition(arr,res+1,right)else: res=self.partition(arr,left,res-1)    return arr[:k]def partition(self,arr,left,right):cur_res=arr[left]while left<right:while left<right and arr[right]>=cur_res:right-=1arr[left]=arr[right]  while left<right and arr[left]<=cur_res:left+=1arr[right]=arr[left]          arr[left]=cur_res        return left

堆排序,这个要注意,求前K小,用的是大根堆排序。先对前K个数字进行排序,然后再从K+1个数开始,如果小于堆顶,则把堆顶推出(说明堆顶肯定不是前K小的数字),将这个数放到堆顶,在进行调整。

class Solution:def getLeastNumbers(self, arr: List[int], k: int) -> List[int]:length=len(arr)  begin=k//2-1while begin>=0:self.adjust_heap(arr,k,begin)begin-=1for i in range(k,length):if arr[i]<arr[0]:#比较这个元素和堆顶元素,若小,arr[0]=arr[i]#则代替堆顶self.adjust_heap(arr,k,0)#进行大根堆排序return arr[:k]#最后返回前K个数即为所求,但不一定有顺序def adjust_heap(self,arr,k,begin):num=beginchild=num*2+1while num<k and child<k:if child+1<k and arr[child]<arr[child+1]:child=child+1if arr[child]>arr[num]:arr[num],arr[child]=arr[child],arr[num]num=childchild=child*2+1

21号——365. 水壶问题

方法一:水壶倒水一共有几种状态,将这些状态全部遍历,然后用一个集合记录经历的状态(防止反复经历,造成无尽的循环)。

class Solution:def canMeasureWater(self, x: int, y: int, z: int) -> bool:stack = [(0, 0)]self.seen = set()while stack:remain_x, remain_y = stack.pop()if remain_x == z or remain_y == z or remain_x + remain_y == z:return Trueif (remain_x, remain_y) in self.seen:continueself.seen.add((remain_x, remain_y))# 把 X 壶灌满。stack.append((x, remain_y))# 把 Y 壶灌满。stack.append((remain_x, y))# 把 X 壶倒空。stack.append((0, remain_y))# 把 Y 壶倒空。stack.append((remain_x, 0))# 把 X 壶的水灌进 Y 壶,直至灌满或倒空。stack.append((remain_x - min(remain_x, y - remain_y), remain_y + min(remain_x, y - remain_y)))# 把 Y 壶的水灌进 X 壶,直至灌满或倒空。stack.append((remain_x + min(remain_y, x - remain_x), remain_y - min(remain_y, x - remain_x)))return False

方法二:数学方法,这个要积累了,应用裴蜀定理

裴蜀定理(或贝祖定理):对任何整数a、b和它们的最大公约数d,关于未知数x和y的线性不定方程(称为裴蜀等式):若a,b是整数,且gcd(a,b)=d,那么对于任意的整数x,y,ax+by都一定是d的倍数,特别地,一定存在整数x,y,使ax+by=d成立。

class Solution:def canMeasureWater(self, x: int, y: int, z: int) -> bool:if x + y < z:return Falseif x == 0 or y == 0:return z == 0 or x + y == zreturn z % math.gcd(x, y) == 0

22号——945. 使数组唯一的最小增量

先把原来的list排序,让每后一个元素均大于前一个元素。每个元素值各不相同,增加最少的次数即位所有。有点贪心算法的意思。

class Solution:def minIncrementForUnique(self, A: List[int]) -> int:A.sort()count=0for i in range(1,len(A)):if A[i-1]>=A[i]:count+=A[i-1]-A[i]+1A[i]=A[i-1]+1return count      

23号——876. 链表的中间结点

自己的解题思路:设计一个right指针,首先遍历一边链表,获得链表长度,计算中心点的位置,然后再移动head指针到最终位置上

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = Noneclass Solution:def middleNode(self, head: ListNode) -> ListNode:if head==None:returnright=head res=1while right.next!=None:right=right.nextres+=1for i in range(res//2):head=head.nextreturn head

看官方解题答案后,觉得使用快慢指针这个思想很好,使用slow,fast两个指针,fast移动速度是slow的两倍,那么等到fast移动到末尾的时候,slow正好在中间。

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = Noneclass Solution:def middleNode(self, head: ListNode) -> ListNode:slow=fast=headwhile fast and fast.next:slow=slow.nextfast=fast.next.nextreturn slow

24号——面试题 17.16. 按摩师

典型的动态规划问题。
分状态回答,设两个状态,
dp[i][0]=max(dp[i-1][0],dp[i-1][1]) #此时没有按摩状态=max(昨天没有按摩状态,昨天有按摩状态)
dp[i][1]=dp[i-1][0]+nums[i] #今天有按摩状态=昨天没有按摩状态+今天按摩了

class Solution:def massage(self, nums: List[int]) -> int:length=len(nums)if length==0:return 0dp_0=tdp_0=0dp_1=nums[0]for i in range(1,length):tdp_0=max(dp_0,dp_1)dp_1=dp_0+nums[i]dp_0=tdp_0return max(dp_0,dp_1) 

相关问题:leetcode动态规划问题

25号——892. 三维形体的表面积

首先一个正方体有6个面,在同一个格子上的,1.要减去摞起来的面,设一个格子内有n个正方体,则要减去2(n-1)个面。2.要减去和这个相邻格子内的立方体的重叠数。

class Solution:def surfaceArea(self, grid: List[List[int]]) -> int:row=len(grid)line=len(grid[0])res=0for i in range(row):for j in range(line):if grid[i][j]==0:#如果这个格子没有立方体,则不做任何操作continueres+=6*grid[i][j]-2*(grid[i][j]-1) #在一个格子内叠起来的立方体for di,dj in [[1,0],[0,-1],[-1,0],[0,1]]:#类似DFS遍历if 0<=i+di<row and 0<=j+dj<line:res-=min(grid[i][j],grid[i+di][j+dj])#减去两个相邻格子间最小数的面return res

26号——999. 车的可用捕获量

这个题有点深度优先遍历的算法思想,但这里没有用递归也没有用栈来辅助,反而用了四次循环的思想。

class Solution:def numRookCaptures(self, board: List[List[str]]) -> int:row=len(board)line=len(board[0])si,sj=0,0dx,dy=[0,1,0,-1],[1,0,-1,0]for i in range(row):for j in range(line):if board[i][j]=="R":si,sj=i,jbreak #先遍历整个数组,找到白色车所在的位置                  res=0     for i in range(4):#四个方向进行step=0while True:new_i=si+dx[i]*stepnew_j=sj+dy[i]*step #新的位置              if new_i<0 or new_i>=8 or new_j<0 or new_j>=8 or board[new_i][new_j]=="B":#若碰到边界或者碰到白色的象break                    if board[new_i][new_j]=="p":#若碰到黑色的车res+=1breakstep+=1 #如果什么都没碰到,那继续向前走        return res              

27号——914. 卡牌分组

先统计每个数字出现的次数,然后取各个出现次数的公约数,如果最大公约数大于2,则可以分组。

class Solution:def hasGroupsSizeX(self, deck: List[int]) -> bool:from fractions import gcdcount=collections.Counter(deck).values()return reduce(gcd,count)>=2

28号——820. 单词的压缩编码

这个题的内容对于我来说是一种崭新的内容。官方题解中用了两种方法:
方法一:存储后缀

1.discard()函数:discard() 方法用于移除指定的集合元素。 该方法不同于 remove() 方法,因为 remove() 方法在移除一个不存在的元素时会发生错误,而 discard() 方法不会。

class Solution:def minimumLengthEncoding(self, words: List[str]) -> int:good = set(words)for word in words:for k in range(1, len(word)):good.discard(word[k:]) #例如good={time,me},那么操作过程是,移除"ime"(没有),移除"me"(有,移除me)return sum(len(word) + 1 for word in good)

方法二:字典树
借鉴这位大佬的代码:https://leetcode-cn.com/problems/short-encoding-of-words/solution/python-zi-dian-shu-by-amir-6/
构造字典树是将字符串从后往前处理。最后的答案是叶子的层数+1.

这里借鉴两个大佬所写的
1.用递归

class Solution:def minimumLengthEncoding(self, words: List[str]) -> int:class Node:def __init__(self, l):  self.l = l # 层数self.children = {}root = Node(0)def build(t, w): # 递归构造字典树if not w:returnif w[-1] not in t.children:t.children[w[-1]] = Node(t.l + 1)build(t.children[w[-1]], w[:-1])for w in words:build(root, w)ans = [0] # 相当于全局变量,以便在递归中累加def vis(t):  # 计算答案if len(t.children) == 0: # 是叶子节点if t.l > 0:ans[0] += t.l + 1 # 累加for c in t.children.values():vis(c)vis(root)return ans[0]


2.不用递归

class Trie:def __init__(self): # 初始化"""Initialize your data structure here."""self.Trie = {}def insert(self, word): # 插入一个单词 word"""Inserts a word into the trie.:type word: str:rtype: void"""curr = self.Trie  # 将字典赋给currfor w in word:  # 循环每个字母if w not in curr: # 如果字母不在字典中curr[w] = {}  # 新建一个字典,用于存储这个w之后的字母curr = curr[w]  # 赋值给curr,这样下一个字母就会继续嵌套在字典的字典里curr['#'] = 1 # 最后一个字母作为key,它的value本来是个{},现在使value='#'def isTail(self, word): # 看word在不在trie中"""Returns if the word is in the trie.:type word: str:rtype: bool"""curr = self.Triefor w in word:curr = curr[w]  # 随着字母的循环,一直走入嵌套的字典中return len(curr) == 1 # 因为最后字母的value是#,# 所以长度是1.如果Trie中没有这个词,那就没有最后的#class Solution:def minimumLengthEncoding(self, words: List[str]) -> int:trie = Trie()  #  初始化一个字典树cnt = 0  # 记录长度words = set(words)  # 将words转为set,去掉重复的单词for word in words:trie.insert(word[::-1])  # 倒序插入字典树中,因为是要判断后缀# 看trie.insert的函数构造,可以看出,如果这个单词是另一个单词的后缀,# 那它是不会成为一条新的分支的,也就是说 判断它isTail是false的,因为要len==1for word in words:if trie.isTail(word[::-1]): # 看这个单词在不在字典树中cnt += len(word) + 1return cnt

参考链接:https://leetcode-cn.com/problems/short-encoding-of-words/solution/python3-hou-zhui-shu-mo-ban-ti-820-dan-ci-de-ya-su/

相关问题:前缀树(Trie)

29号——1162. 地图分析

这道题还是DFSorBFS做法的变形
这里我用DFS来进行

class Solution:def maxDistance(self, grid: List[List[int]]) -> int:row=len(grid)line=len(grid[0])#dist用来存放距离陆地的距离dist=[[float('inf') for _ in range(row)]for _ in range(line)]#visit用来判断这个位置是否访问过visit=[[False for _ in range(row)] for _ in range(line)]queue=collections.deque()land_num=0res=0total=row*line#先将整个表格进行遍历,将陆地位置存入队列for i in range(row):for j in range(line):if grid[i][j]==1:dist[i][j]=0visit[i][j]=Truequeue.append((i,j))land_num+=1#记录陆地数,若全是陆地或者全是海洋,则返回-1           if land_num==total or land_num==0:return -1#然后开始广度优先遍历while queue:x,y=queue.popleft()for i,j in [(x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)]:if 0<=i<row and 0<=j<line and visit[i][j]==False:dist[i][j]=min(dist[i][j],dist[x][y]+1)res=max(res,dist[i][j])visit[i][j]=Truequeue.append((i,j))return res

30号——面试题62. 圆圈中最后剩下的数字

首先先贴一个不是数学方法的方法(毕竟如果是第一次遇见不知道这个数学方法怎么办!)
其实就是用数组记录,如果读取到这个位置就pop出来。

class Solution:def lastRemaining(self, n: int, m: int) -> int:arr=[i for i in range(n)]num=(m-1)%len(arr)while len(arr)!=1:arr.pop(num)num=(num+(m-1))%len(arr)return arr[0]

因为借助了系统已经写好的pop方法,但很明显这样做时间效率很低。

方法二:数学方法
写了半天也没弄清楚,看过答案才知道要用约瑟夫环(??什么东西),然后去补习一波,
借鉴大佬写的,这是我看能看懂的一篇!

class Solution:def lastRemaining(self, n: int, m: int) -> int:num=0for i in range(2,n+1):num=(num+m)%ireturn num

31号——912. 排序数组


这道题没什么难的,主要是练习各种排序问题的写法。这些模版需要好好理解背过。

相关问题:几种要会书写的排序方法

1.快排

class Solution:def sortArray(self, nums: List[int]) -> List[int]:left=0right=len(nums)-1self.quickSort(nums,left,right)return numsdef quickSort(self,nums,left,right):if left<right:pi=self.partition(nums,left,right)self.quickSort(nums,left,pi)self.quickSort(nums,pi+1,right)     def partition(self,nums,left,right):num=nums[left]while left<right:while left<right and nums[right]>=num:right-=1nums[left]=nums[right]while left<right and nums[left]<=num:left+=1nums[right]=nums[left]nums[left]=numreturn left


2.归并排序

class Solution:def sortArray(self, nums: List[int]) -> List[int]:nums=self.merge_sort(nums)return numsdef merge_sort(self,nums):if len(nums)==1:return numsmid=len(nums)//2left=nums[:mid]right=nums[mid:] #从第m+1个元素取到最后return self.merge(self.merge_sort(left),self.merge_sort(right))def merge(self,left,right):res=[]i,j=0,0while i<len(left) and j<len(right):if left[i]<right[j]:res.append(left[i])i+=1else:res.append(right[j])j+=1res+=left[i:]res+=right[j:]return res

3.堆排序
原理感觉这个视频讲的很好:
https://www.bilibili.com/video/av18980178?from=search&seid=3518072115040122033

class Solution:def sortArray(self, nums: List[int]) -> List[int]:nums=self.heapSort(nums)return numsdef heapSort(self,nums):n=len(nums)#首先是建堆,建成大根堆的模样for i in range(n//2-1,-1,-1):self.adjustHeap(nums,i,n)#开始调整堆,因为堆顶现在是最大元素,所以把堆顶和最后一个元素交换,再对除去最后一个元素的堆进行调整。for i in range(n-1,-1,-1):nums[0],nums[i]=nums[i],nums[0]self.adjustHeap(nums,0,i)return numsdef adjustHeap(self,nums,start,end):num=nums[start]pos=startchildpos=pos*2+1while childpos<end:rightpos=childpos+1if rightpos<end and nums[childpos]<nums[rightpos]:childpos=rightpos #比较两个孩子结点的大小,让指针指向大一点的那个if num<nums[childpos]:nums[pos]=nums[childpos]pos=childposchildpos=pos*2+1 #开始进行结点调整,让大的结点往上走else:breaknums[pos]=num

4.计数排序
有点哈希思想,统计每个数字出现的次数,然后从小到大输出。

class Solution:def sortArray(self, nums: List[int]) -> List[int]:if not nums:return []n=len(nums)min_num=min(nums)max_num=max(nums)arr=[0]*(max_num-min_num+1)for num in nums:arr[num-min_num]+=1 #arr用来统计原来每个num出现的次数j=0for i in range(n):while arr[j]==0:j+=1nums[i]=j+min_numarr[j]-=1return nums

可以看到时间是最快的了吧

5.桶排序
这道题桶排序不明显(有点类似于计数排序的加强版,现根据桶的要求归类,再把每个桶内进行排序),这里贴一下大佬写的代码吧。
https://leetcode-cn.com/problems/sort-an-array/solution/python-shi-xian-de-shi-da-jing-dian-pai-xu-suan-fa/

def bucket_sort(nums, bucketSize):if len(nums) < 2:return nums_min = min(nums)_max = max(nums)# 需要桶个数bucketNum = (_max - _min) // bucketSize + 1buckets = [[] for _ in range(bucketNum)]for num in nums:# 放入相应的桶中buckets[(num - _min) // bucketSize].append(num)res = []for bucket in buckets:if not bucket: continueif bucketSize == 1:res.extend(bucket)else:# 当都装在一个桶里,说明桶容量大了if bucketNum == 1:bucketSize -= 1res.extend(bucket_sort(bucket, bucketSize))return res

你不得不看的leetcode常见题(3月份每日一题)——Python相关推荐

  1. 【LeetCode】2022 7月 每日一题

    [LeetCode]2022 7月 每日一题 前言 七月太忙了,又是项目又是练车又是各种比赛.大概有10天的每日一题没有当天写完(虽然后面补上了). 将每日一题的所有思路记录在这里分享一下. 7.1 ...

  2. Leetcode 006. Z 字形变换 | 每日一题

    题目描述: 将一个给定字符串根据给定的行数,以从上往下.从左到右进行Z 字形排列. 比如输入字符串为 "LEETCODEISHIRING" 行数为 3 时,排列如下: L C I ...

  3. [每日一题]0:每日一题汇总

    每日一题 锻炼编程能力,每日尽量至少更新一道算法编程题,博客内主要更新学习C/C++.以及Linux的相关知识点,希望在记录学习过程的同时也能方便遇到相同问题的人,方便回顾复习,也希望能够与大家一起交 ...

  4. Leetcode 142. 环形链表 II (每日一题 20210902)

    给定一个链表,返回链表开始入环的第一个节点. 如果链表无环,则返回 null.为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始). 如果 pos 是 -1 ...

  5. Leetcode 18. 四数之和 (每日一题 20211011)

    给你一个由 n 个整数组成的数组 nums ,和一个目标值 target .请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] : ...

  6. Leetcode 59. 螺旋矩阵 II (每日一题 20210926)

    给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix .示例 1:输入:n = 3 输出:[[1,2,3],[8,9,4],[ ...

  7. Leetcode 45. 跳跃游戏 II (每日一题 20210922)

    给你一个非负整数数组 nums ,你最初位于数组的第一个位置.数组中的每个元素代表你在该位置可以跳跃的最大长度.你的目标是使用最少的跳跃次数到达数组的最后一个位置.假设你总是可以到达数组的最后一个位置 ...

  8. Leetcode 876. 链表的中间结点 (每日一题 20210918)

    给定一个头结点为 head 的非空单链表,返回链表的中间结点.如果有两个中间结点,则返回第二个中间结点.示例 1:输入:[1,2,3,4,5] 输出:此列表中的结点 3 (序列化形式:[3,4,5]) ...

  9. Leetcode 217. 存在重复元素 (每日一题 20210913)

    给定一个整数数组,判断是否存在重复元素.如果存在一值在数组中出现至少两次,函数返回 true .如果数组中每个元素都不相同,则返回 false .示例 1:输入: [1,2,3,1] 输出: true ...

最新文章

  1. 久等!2020智源大会演讲视频全公开,参与盖楼挑战赢限量徽章
  2. java 类中构造函数的讲解
  3. kafka-python 停止消费
  4. Spring5 - Bean的初始化和销毁的4种方式
  5. 笔记-中项案例题-2018年上-人力资源管理
  6. CodeForces - 1516D Cut(思维+倍增)
  7. c 最大子序列和_算法总结:左神class8—跳台阶+最长递增公共子序列
  8. 数据分析常用Python库:数值计算、可视化、机器学习等领域
  9. 整理90部好看的经典喜剧片
  10. Python机器学习:评价分类结果004F1score
  11. python oserror路径not found_python基本操作-文件、目录及路径
  12. 多个html页面拼接成一个页面_浏览器渲染页面机制以及如何减少DOM操作
  13. nginx: [emerg] mkdir() /var/temp/nginx/client failed (2: No such file or directory)
  14. html木马制作教程,利用Internet Explorer Object Data漏洞制做全新网页木马
  15. python垃圾分类图像处理_教你用Python轻松解决垃圾分类这个头疼的问题!
  16. 【web攻防】CVE-2020-10487 tomcat 文件包含漏洞 docker 复现学习
  17. 给定秒数 seconds ,把秒转化成小时、分钟和秒
  18. 自定义控件——圆形圆点进度条(仿安全卫士中的一键加速)
  19. 【Command】sudo rm -rf /* 啥效果?
  20. SA(需求分析师)笔试题目整理

热门文章

  1. pythonrandint用法_Python:randint()用法
  2. OsgEarth3基础3D图形实现
  3. X-Argus X-Gorgon X-Ladon findcrypt和findhash查找疑似加密函数(五)
  4. CentOS安装gnome dask to dock插件
  5. could not fetch initial value for increment genera
  6. R语言acres92 region_R语言学习笔记(四)
  7. navicat10.1.7 注册码
  8. 什么是SSH与SSH客户端
  9. 数学之美:凸优化问题
  10. 泰坦尼克号python存活率预测--学习笔记