- 一、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 np
matrix = [[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:]
# right
if len(matrix) > 0:
for i in range(row - 1):
output.append(matrix[i][-1])
matrix = matrix[:, :-1]
# bottom
if len(matrix) > 0:
for i in reversed(range(col - 1)):
output.append(matrix[-1][i])
matrix = matrix[:-1]
# left
if 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 output
def 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 - 1
output = []
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 += 1
return output
print(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方法会删掉第一次出现的指定值value
else:
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.col2
from (
select
*,
row_number() over(partition by col1,col2) as rn
from t1
) t1 left join (
select
*,
row_number() over(partition by col1,col2) as rn
from t2
) t2 on t1.col1=t2.col1 and t1.col2=t2.col2 and t1.rn=t2.rn
where 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 rn
from t1
) t1 left join (
select
*,
row_number() over(partition by col1,col2) as rn
from t2
) t2 on t1.col1=t2.col1 and t1.col2=t2.col2 and t1.rn=t2.rn
where t2.col1 is null;