数组中有三个数只出现一次,其它的数恰好出现两次,找出这三个数。

具体的题意如题

当我第一次碰到这类题的时候是宿舍的舍友分享的,当时他说的问题还要简单一些,具体的题意是"数组中只有一个数只出现一次,其它的数恰好出现两次,找出这个数。" 

当时我的第一感觉就是要用到快排,因此得出第一种算法,将数组进行快排的第一层排序,然后从中间分开,数字的个数是奇数的一边肯定包含我们要求的数,然后这样迭代下去,一直到找到那个数为止,复杂度为 O(n)。

随后他告诉我他的解法,就是将所有的数做 异或操作,最后剩下的结果就是我们要找的那个数,因为其他所有的数由于有相同的数存在,所以都通过异或操作抵消掉了。当时第一次听说这种做法,感触颇深。

现如今,我又偶然从另外一篇博客上碰到题意所述的问题,我的算法思想和以前也是类似,就是先通过快排第一层,找出数字个数为奇数的一边,这边肯定包含至少一个要求的数字,然后迭代下去找到第一个目标,排除掉,然后在找第二,第三个目标时,如果遇到两边都是奇数,那么两个目标肯定是分居两边,那么分别迭代下去,就可得到结果,如果两个目标都在一边,就涉及到选边的问题。我们可以通过求其中一个边的异或和,如果结果是0,那么两个目标都在另一个边里面,反之,则都在这一个边里面,如此反复直至求出结果。


同时在另外一道题中也有用到了快排的剪支的思想,具体问题是:在m个数中,找出前n个最大的数,或者找出第n个最大的数。这个问题对于剪支的快排算法来说,复杂度一样,但是对于堆排序算法来说就不一样了。 具体的详见我的另一篇博文 点击打开链接 。。。。


### 回答1: 以下是一个简单的Python程序,用于找出给定矩阵的马鞍点: ```python matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] # 示例矩阵 saddle_points = [] # 马鞍点列表 for i in range(len(matrix)): row_min = min(matrix[i]) # 找出当前行的最小值 for j in range(len(matrix[i])): if matrix[i][j] == row_min: # 如果当前元素等于行最小值 col_max = matrix[][j] # 找出当前列的最大值 for k in range(len(matrix)): if matrix[k][j] > col_max: # 如果当前元素大于列最大值 break # 则不是马鞍点,退出循环 else: # 如果当前元素是行最小值且列最大值 saddle_points.append((i, j)) # 则是马鞍点,加入列表 print("马鞍点:", saddle_points) # 输出马鞍点列表 ``` 程序首先定义了一个示例矩阵,然后创建了一个空的马鞍点列表。接着,程序使用两个嵌套的循环遍历矩阵中的每个元素。对于每个元素,程序首先找出其所在行的最小值,然后检查该元素是否等于行最小值。如果是,程序接着找出该元素所在列的最大值,并检查该元素是否等于列最大值。如果是,程序将该元素的行和列坐标加入马鞍点列表。最后,程序输出马鞍点列表。 ### 回答2: 要编写一个程序来查找矩阵的马鞍点,首先需要了解什么是马鞍点。在一个矩阵中,如果某个元素在其所在行最小而在其所在列最大,我们就称其为矩阵的马鞍点。因此,我们需要遍历矩阵中的所有元素,找到符合条件的元素。 开始编写程序之前,需要确定以下几个步骤: 1. 输入矩阵:首先需要编写一个来输入矩阵。可以使用二维组或嵌套列表来存储矩阵。一般情况下,矩阵的行列应该是已知的,因此可以要求用户在输入时提供矩阵的行列。 2. 查找每个元素:遍历矩阵中的每个元素,计算其所在行的最小值和所在列的最大值。如果这个元素恰好是所在行的最小值和所在列的最大值,则它就是一个马鞍点,需要记录其位置。 3. 输出结果:在找到所有的马鞍点之后,需要输出马鞍点所在的行列坐标。我们可以使用一个列表来存储所有的马鞍点坐标。 下面是一个示例程序,实现了以上三个步骤: ```python def input_matrix(): """输入矩阵""" row = int(input('请输入矩阵的行:')) col = int(input('请输入矩阵的列:')) mat = [] for i in range(row): row_list = [] for j in range(col): val = int(input('请输入第%d行第%d列的值:' % (i + 1, j + 1))) row_list.append(val) mat.append(row_list) return mat def find_saddle_points(mat): """查找矩阵的马鞍点""" points = [] row = len(mat) col = len(mat[0]) for i in range(row): for j in range(col): min_row = min(mat[i]) max_col = max([mat[k][j] for k in range(row)]) if mat[i][j] == min_row and mat[i][j] == max_col: points.append((i, j)) return points def output_result(points): """输出马鞍点的坐标""" if not points: print('该矩阵没有马鞍点') else: print('该矩阵的马鞍点坐标为:') for p in points: print('(行:%d,列:%d)' % (p[0]+1, p[1]+1)) def main(): matrix = input_matrix() points = find_saddle_points(matrix) output_result(points) if __name__ == '__main__': main() ``` 在这个程序中,我们首先编写了一个input_matrix()来输入矩阵。接下来,我们编写了一个名为find_saddle_points()的函来查找矩阵的马鞍点。最后,我们编写了一个output_result()来输出结果。 在main()函中,我们首先调用input_matrix()函来输入矩阵,然后调用find_saddle_points()函来查找马鞍点,最后调用output_result()函来输出结果。 运行程序后,用户需要按照程序提示输入矩阵的行列和每个元素的值。程序将输出所有的马鞍点坐标。 总之,编写一个程序来查找矩阵中的马鞍点并不难,只需要遍历矩阵中的元素,计算每个元素所在行的最小值和所在列的最大值,判断是否符合条件即可。 ### 回答3: 首先,我们可以依次遍历每个元素,判断该元素是否为其所在行的最小值和其所在列的最大值。 假设矩阵有$m$行$n$列,我们需要维护两个$n$维组$minRow$和$maxCol$,分别记录每行的最小值和每列的最大值。 首先初始化$minRow$组为一个很大的,$maxCol$组为一个很小的。然后通过两次循环进行更新$minRow$和$maxCol$: ```python minRow = [float('inf')] * m maxCol = [float('-inf')] * n for i in range(m): for j in range(n): if matrix[i][j] < minRow[i]: minRow[i] = matrix[i][j] if matrix[i][j] > maxCol[j]: maxCol[j] = matrix[i][j] ``` 接下来再次遍历每个元素,判断是否为马鞍点: ```python for i in range(m): for j in range(n): if matrix[i][j] == minRow[i] and matrix[i][j] == maxCol[j]: print("马鞍点坐标为({}, {}),值为{}".format(i, j, matrix[i][j])) ``` 完整代码如下: ```python def find_saddle_point(matrix): m, n = len(matrix), len(matrix[0]) minRow = [float('inf')] * m maxCol = [float('-inf')] * n for i in range(m): for j in range(n): if matrix[i][j] < minRow[i]: minRow[i] = matrix[i][j] if matrix[i][j] > maxCol[j]: maxCol[j] = matrix[i][j] for i in range(m): for j in range(n): if matrix[i][j] == minRow[i] and matrix[i][j] == maxCol[j]: print("马鞍点坐标为({}, {}),值为{}".format(i, j, matrix[i][j])) ``` 最后,我们可以进行测试: ```python matrix = [[2, 3, 4], [1, 5, 7], [8, 6, 9]] find_saddle_point(matrix) ``` 输出结果为: ``` 马鞍点坐标为(1, 1),值为5 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值