- 一、apple外包
- 1.矩阵顺时针旋转遍历
- 2.两表取差集
- 二、
一、apple外包
没问理论,就两个算法题。
1.矩阵顺时针旋转遍历
Given an m x n matrix, return all elements of the matrix in spiral order.Example 1:Input: matrix = [[1,2,3],[4,5,6],[7,8,9]]
Output: [1,2,3,6,9,8,7,4,5]Example 2:Input: matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
Output: [1,2,3,4,8,12,11,10,9,5,6,7]Constraints:m == matrix.length
n == matrix[i].length
1 <= m, n <= 10
-100 <= matrix[i][j] <= 100
这题当时没写出来,一直想基于矩阵的下标使用循环完成,因为对于顺时针循环,横纵坐标x, y的变化特点是x, y先分别自增,然后分别自减。当时因为在边界值这块没处理好代码一直没跑起来。后来面试完才想起来切片实现就不用太考虑边界值的问题了。下面分别按照切片的方式和动态调整边界值的方式重新解下这道题。
import pandas as pd
import numpy as npmatrix = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]def solution1(matrix):"""方法一:通过切片方式实现"""row, col = len(matrix), len(matrix[0])matrix = np.asarray(matrix).reshape(row, col)output = []while len(matrix) > 0: # 无论横着切还是竖着切,当二维矩阵被切完时会变成一维数组# top 注意切片取值范围[)for i in range(col):output.append(matrix[0][i])matrix = matrix[1:]# rightif len(matrix) > 0:for i in range(row - 1):output.append(matrix[i][-1])matrix = matrix[:, :-1]# bottomif len(matrix) > 0:for i in reversed(range(col - 1)):output.append(matrix[-1][i])matrix = matrix[:-1]# leftif len(matrix) > 0:for i in reversed(range(row - 2)):output.append(matrix[i][0])matrix = matrix[:, 1:]if len(matrix) > 0:row, col = len(matrix), len(matrix[0])else:return outputdef solution2(matrix):"""方法二:通过矩阵的上下左右四个边界值,每遍历完一个边界动态的调整该边界的边界值实现"""row, col = len(matrix), len(matrix[0])matrix = np.asarray(matrix).reshape(row, col)top, bottom, left, right = 0, row - 1, 0, col - 1output = []while left <= right and top <= bottom:# 刚进入while循环可以不用卡边界,此时边界值还未调整# 遍历上边界,+1是因为range取值[),后面-1也是同理for i in range(left, right + 1):output.append(matrix[top][i])top += 1# 上下遍历时需要卡左右边界没有互相越界# 遍历右边界if left <= right:for i in range(top, bottom + 1):output.append(matrix[i][right])right -= 1# 左右遍历卡上下边界未越界# 遍历下边界if top <= bottom:for i in range(right, left - 1, -1):output.append(matrix[bottom][i])bottom -= 1# 遍历左边界if left <= right:for i in range(bottom, top - 1, -1):output.append(matrix[i][left])left += 1return outputprint(f"方法1:{solution1(matrix)}")
print(f"方法2:{solution2(matrix)}")
2.两表取差集
The difference(Relative Complement) between two sets A and B is defined as A - B := {x|x ∈ A ∧ x ∉ B}. Assume that the set allows duplicate elements. For example, the difference between A = (5, 6, 6, 7) and B = (6, 7, 8) is A - B = (5, 6).Consider each row in a Table as element of the set. Given two Tables t1 and t2, return the difference t1 - t2.Note that column names in two Tables are identical.Example 1:Input:
+-------------+
| t1 |
+------+------+
| col1 | col2 |
+------+------+
| 1 | 3 |
| 1 | 4 |
| 1 | 4 |
| 2 | 5 |
| 4 | 5 |
+------+------++-------------+
| t2 |
+------+------+
| col1 | col2 |
+------+------+
| 1 | 3 |
| 1 | 4 |
| 1 | 6 |
| 2 | 5 |
| 3 | 5 |
+------+------+Output:
+-------------+
| output |
+------+------+
| col1 | col2 |
+------+------+
| 1 | 4 |
| 4 | 5 |
+------+------+Example 2:Input:
+-------------+
| t1 |
+------+------+
| col1 | col2 |
+------+------+
| 1 | 3 |
| 1 | 4 |
| 1 | 4 |
+------+------++-------------+
| t2 |
+------+------+
| col1 | col2 |
+------+------+
| 1 | 3 |
| 1 | 4 |
| 1 | 4 |
| 1 | 4 |
| 3 | 5 |
+------+------+Output:
+-------------+
| output |
+------+------+
| col1 | col2 |
+------+------+
+------+------+
面试中用的最简单直接的方式解决,依次判断t1中的元素是否在t2中,在的话都移出去:
import pandas as pd# Example 1:
t1 = pd.DataFrame(data=[[1, 3], [1, 4], [1, 4], [2, 5], [4, 5]], columns=['col1', 'col2'])
t2 = pd.DataFrame(data=[[1, 3], [1, 4], [1, 6], [2, 5], [3, 5]], columns=['col1', 'col2'])def solution(t1, t2):list1 = t1.values.tolist()list2 = t2.values.tolist()res = []for value in list1:if value in list2:list2.remove(value) # remove方法会删掉第一次出现的指定值valueelse:res.append(value)return pd.DataFrame(data=res, columns=['col1', 'col2'])print(solution(t1, t2))
这题一开始我想用SQL实现,但是因为两个表里都可以有重复数据,比如说对于数据A,t1表有两个A,t2表有一个A,那么关联的时候t1的两个A都能和t2的一个A关联上,而根据题意,t1两个A减去t2一个A,还应剩下一个A,当时的卡点在这。导致SQL的实现没有完成,后被提示开窗函数,才想起来可以通过row_number为相同的A打上序号标签,关联的时候加上序号限制就可以了。
下面是具体代码实现:
import pandas as pd
from pandasql import sqldf"""
因为涉及到开窗函数,所以不能仅通过pandas中的join完成需求。查看pandas的api发现并不能直接基于df写sql
查看资料后发现可以通过引入第三方库pandasql实现。pandasql文档:https://pypi.org/project/pandasql/0.7.3/
"""# Example 1:
t1 = pd.DataFrame(data=[[1, 3], [1, 4], [1, 4], [2, 5], [4, 5]], columns=['col1', 'col2'])
t2 = pd.DataFrame(data=[[1, 3], [1, 4], [1, 6], [2, 5], [3, 5]], columns=['col1', 'col2'])def solution(t1, t2):pysqldf = lambda q: sqldf(q, globals())return pysqldf("""select distinct t1.col1, t1.col2from (select*,row_number() over(partition by col1,col2) as rnfrom t1) t1 left join (select*,row_number() over(partition by col1,col2) as rnfrom t2) t2 on t1.col1=t2.col1 and t1.col2=t2.col2 and t1.rn=t2.rnwhere t2.col1 is null;""")print(solution(t1, t2))
但是上面的代码总是报SQL语法错误,查资料后说的是sqlite3的版本低了,不支持开窗函数,从3.25.0开始支持,我的是3.21.0,升级标准库还需要升级解释器,为了方便直接通过下面代码把数据同步到mysql中实现:
import pandas as pd
from sqlalchemy import create_engine# Example 1:
t1 = pd.DataFrame(data=[[1, 3], [1, 4], [1, 4], [2, 5], [4, 5]], columns=['col1', 'col2'])
t2 = pd.DataFrame(data=[[1, 3], [1, 4], [1, 6], [2, 5], [3, 5]], columns=['col1', 'col2'])engine = create_engine('mysql+pymysql://root:123456@localhost/demo')
t1.to_sql('t1', engine, index=False)
t2.to_sql('t2', engine, index=False)
select distinct t1.col1, t1.col2
from (select*,row_number() over(partition by col1,col2) as rnfrom t1
) t1 left join (select*,row_number() over(partition by col1,col2) as rnfrom t2
) t2 on t1.col1=t2.col1 and t1.col2=t2.col2 and t1.rn=t2.rn
where t2.col1 is null;