23/8/27刷题记录

1. pandas 数据分组

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]

2. 剑指offer 双指针

剑指 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) #拼接返回

3. 剑指offer 查找

剑指 Offer 03. 数组中重复的数字【简单】

23/8/27刷题记录_第1张图片
原地交换,时间O(N),空间O(1)

  1. 遍历数组 nums ,设索引初始值为 i=0 :
  • 若 nums[i]=i : 说明此数字已在对应索引位置,无需交换,因此跳过;
  • 若 nums[nums[i]]=nums[i] : 代表索引 nums[i]处和索引 i处的元素值都为 nums[i],即找到一组重复值,返回此值 nums[i] ;
  • 否则: 交换索引为 i和 nums[i]的元素值,将此数字交换至对应索引位置。
  1. 若遍历完毕尚未返回,则返回 −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可以控制坐标的增长区间,原地交换的方法

你可能感兴趣的:(算法刷题记录,python,力扣)