1741. 查找每个员工花费的总时间【简单】
在这段代码中,注意分组函数groupby的运用
def total_time(employees: pd.DataFrame) -> pd.DataFrame:
# 新建一列保存
employees['total_time'] = employees['out_time'] - employees['in_time']
# 多索引分组,对某列单独求和,重置索引
employees = employees.groupby(['event_day','emp_id'])['total_time'].sum().reset_index()
#更改名字,沿着横轴,表示对列进行操作
employees.rename({'event_day':'day'},axis=1,inplace=True)
employees['day'] = employees['day'].astype(str)
return employees
511. 游戏玩法分析 I【简单】
注意这里的rename,更改列变成了columns,而上一题的表达是axis = 1
def game_analysis(activity: pd.DataFrame) -> pd.DataFrame:
activity = activity.groupby(['player_id'])['event_date'].min().reset_index()
activity = activity.rename(columns = {'event_date':'first_login'})
return activity[['player_id','first_login']]
2356. 每位教师所教授的科目种类的数量【简单】
注意nunique
def count_unique_subjects(teacher: pd.DataFrame) -> pd.DataFrame:
# 给教师按照id分组,计算科目数量,即不重复的subject_id,形成新的teacher
df = teacher.groupby(['teacher_id'])['subject_id'].nunique().reset_index()
df = df.rename({'subject_id':'cnt'},axis = 1)
return df
596. 超过5名学生的课【简单】
注意reset_index
和size
def find_classes(courses: pd.DataFrame) -> pd.DataFrame:
# 按照class分组,计算student数量,然后使用 reset_index() 方法将结果转换为 DataFrame,并将列名命名为 'cnt'
df = courses.groupby(['class'])['student'].size().reset_index(name='cnt')
# 筛选符合条件的班级
df = df[df['cnt'] >= 5]
return df[['class']]
586. 订单最多的客户【简单】
这题注意不同分组的比较
def largest_orders(orders: pd.DataFrame) -> pd.DataFrame:
# 分组
# df = orders.groupby(['customer_number'])['order_number'].max().reset_index() 获得每个分组下的最大值
df = orders.groupby(['customer_number'])['order_number'].size().reset_index(name = 'cnt')
# 排序,对不同组的数进行比较
df.sort_values(by = 'cnt', ascending = False, inplace = True)
return df[['customer_number']][:1]
剑指 Offer 52. 两个链表的第一个公共节点
【简单】
方法一:哈希表,时间O(M+N),空间O(N)
// 哈希表
class Solution {
ListNode getIntersectionNode(ListNode headA, ListNode headB) {
Set<ListNode> visited = new HashSet<ListNode>();
ListNode tmp = headA;
while(tmp != null){
visited.add(tmp);
tmp = tmp.next;
}
tmp = headB;
while(tmp != null){
if(visited.contains(tmp)){
return tmp;
}
tmp = tmp.next;
}
return null;
}
}
方法二:双指针 时间O(M+N),空间O(1)
如果存在交点:第一条链表首次到达「第一个相交节点」的充要条件是第一条链表走了 a+c+b步,由于两条链表同时出发,并且步长相等,因此当第一条链表走了 a+c+b步时,第二条链表同样也是走了 a+c+b步,即 第二条同样停在「第一个相交节点」的位置。
如果不存在交点:两者会在走完 a+c+b+ca + c + b + ca+c+b+c 之后同时变为 nullnullnull,退出循环。
# 双指针法
class Solution:
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
a,b = headA, headB
while a != b:
a = a.next if a else headB
b = b.next if b else headA
return a
剑指 Offer 21. 调整数组顺序使奇数位于偶数前面【简单】
自己写出来了!快排的思想,哨兵划分【个人想法】
时间O(N),空间O(1)
def exchange(self, nums: List[int]) -> List[int]:
# 设置指针
l,r = 0, len(nums)-1
while l < r:
while l < r and nums[l] % 2 != 0: l += 1
while l < r and nums[r] % 2 == 0: r -= 1
nums[l],nums[r] = nums[r],nums[l]
return nums
剑指 Offer 57. 和为s的两个数字【简单】
def twoSum(self, nums: List[int], target: int) -> List[int]:
# 设置双指针
l,r = 0 , len(nums)-1
while l < r:
s = nums[l] + nums[r]
# 注意没用while
if s > target: r -= 1
elif s < target: l += 1
else: return [nums[l],nums[r]]
return []
[剑指 Offer 58 - I. 翻转单词顺序【简单】
(https://leetcode.cn/problems/fan-zhuan-dan-ci-shun-xu-lcof/?envType=study-plan-v2&envId=coding-interviews)
注意字符串的切分
def reverseWords(self, s: str) -> str:
# 删除首尾空格
s = s.strip()
#初始化双指针
l = r = len(s)-1
# 结果返回
res = []
# 循环开始
while l >= 0:
while l >=0 and s[l] != ' ': l -= 1 #搜寻空格
res.append(s[l + 1: r + 1]) #因为此时l位置是空格,往后一位才是字母,r+1 实际上取到的是r
while s[l] == ' ' : l -= 1
r = l # 把右边界指向上一个单词的首部
return ' '.join(res) #拼接返回
剑指 Offer 03. 数组中重复的数字【简单】
原地交换,时间O(N),空间O(1)
def findRepeatNumber(self, nums: List[int]) -> int:
i = 0
while i < len(nums):
if nums[i] == i:
i += 1 # 注意这一步就i++了,所以不用for
continue
# 如果位置对了,返回重复值
if nums[nums[i]] == nums[i]: return nums[i]
# 位置不对,交换
nums[nums[i]] , nums[i] = nums[i],nums[nums[i]]
return -1
数组划分,列的计数,不同列的大小比较
双指针主要是左右指针的移动
用while可以控制坐标的增长区间,原地交换的方法