网友吐槽:外包做事真是极其不负责,一点owner精神都没有,活该当一辈子外包。。
今天看到一个关于外包的讨论,我真是忍不住想聊聊。
网友吐槽外包做事“真是极其不负责,搭个Grafana面板半个月出不来”,还说“自己一点owner精神都没有,一辈子外包,别怪别人看不起外包”。这话听着真是让人有点气又有点笑。
我觉得吧,外包和正式员工的心态差别真的很大。你看,外包做事是按小时或者按项目收费,他们可不会像我们这些正式员工一样,把公司当成自己的家。
举个例子,我们技术部门也有过外包合作,刚开始觉得省心,外包能快速出活。但往往问题来了——沟通不顺畅,交付时间也不靠谱。
但是也是能理解的,毕竟人家就拿那点钱,拿的钱少,总不能事多还背责吧
你说,这事儿是不是得怪外包?当然,外包公司本身也有责任,但作为雇主,你不给够钱,那他们当然不会像正式员工一样给你发奋图强。
最后,那位网友评论说“希望全行业招正编”,这个我倒是认同。要想提高工作效率和项目质量,稳定的核心团队是最重要的!
所以说,外包有外包的优点,但也有它的局限,要质量还得正编~【备注:文末可领最新资料】
算法题:K 个逆序对数组
今天我们来聊聊一个经典的算法题:K个逆序对数组。
先给大家一个题目描述:
给定一个整数数组,你需要找到其中存在多少对逆序对。所谓逆序对,就是对于数组中的任意一对元素(i, j),如果i < j且arr[i] > arr[j],那就称arr[i]和arr[j]构成一个逆序对。
好,题目说得很清楚,关键是如何解决。我们来逐步分析。
如果你直接用暴力破解法去做,可能会有点崩溃。暴力方法的时间复杂度是O(n²),因为你要对每一对元素都进行比较,看看它们是否构成逆序对。显然,当数组长度比较大时,O(n²)的时间复杂度会让人头皮发麻,效率低得不忍直视。
比如这个数组:[5, 2, 6, 1]
通过暴力方法,依次比较,每一对(i, j)都能找出逆序对。比如5 > 2,5 > 1,6 > 1,这些都构成逆序对,总共的逆序对是3。
这种方法虽然简单,但效率实在是太低了,我们要想办法优化。
优化思路
既然暴力法不行,那就让我们试试更高级的技术:归并排序。
这看似和排序没有什么关系,但归并排序的过程中其实就能顺便统计逆序对。为什么呢?因为归并排序在合并两个有序子数组时,如果左边的元素比右边的元素大,那么这两个元素以及所有左边元素和右边右侧元素都会形成逆序对。
举个例子,假设有两个已经排好序的数组:
[1, 3, 5] 和 [2, 4, 6]
在合并这两个数组时,我们会发现1小于2,就继续比较下一个,直到3和2的比较。这里如果3 > 2,那就会形成一个逆序对。并且,所有左边的元素[1, 3, 5]都大于右边的元素2,所以这些比较就能够顺便统计逆序对。
代码实现
我们可以利用归并排序的思想来统计逆序对。以下是一个实现的示例:
def merge_count_split_inv(arr, temp_arr, left, right):
if left == right:
return 0
mid = (left + right) // 2
inv_count = merge_count_split_inv(arr, temp_arr, left, mid)
inv_count += merge_count_split_inv(arr, temp_arr, mid + 1, right)
inv_count += merge_and_count(arr, temp_arr, left, mid, right)
return inv_countdef merge_and_count(arr, temp_arr, left, mid, right):
i = left # Starting index for left subarray
j = mid + 1 # Starting index for right subarray
k = left # Starting index to be sorted
inv_count = 0
while i <= mid and j <= right:
if arr[i] <= arr[j]:
temp_arr[k] = arr[i]
i += 1
else:
temp_arr[k] = arr[j]
inv_count += (mid - i + 1) # All the remaining elements in left subarray are greater than arr[j]
j += 1
k += 1
while i <= mid:
temp_arr[k] = arr[i]
i += 1
k += 1
while j <= right:
temp_arr[k] = arr[j]
j += 1
k += 1
for i in range(left, right + 1):
arr[i] = temp_arr[i]
return inv_count
def count_inversions(arr):
temp_arr = [0] * len(arr)
return merge_count_split_inv(arr, temp_arr, 0, len(arr) - 1)
# 测试代码
arr = [5, 2, 6, 1]
print(f"逆序对数量为:{count_inversions(arr)}")
这段代码用归并排序的方法统计逆序对。首先,我们实现了merge_and_count函数来合并两个子数组并计算逆序对。在合并过程中,每当左边的元素比右边的元素大时,说明构成了逆序对。而且,左边当前元素之后的所有元素也都比右边的当前元素大。
整体的时间复杂度为O(n log n),比暴力方法的O(n²)快得多,适用于较大的数据集。
总结
通过归并排序方法,逆序对的计算问题变得高效且可扩展。归并排序本身的时间复杂度是O(n log n),通过在归并的过程中统计逆序对,我们避免了暴力算法的低效性能。这也是算法优化中常见的一种技巧:将原本的任务转化为一个更高效的过程中去完成。
如果你面试时遇到这种问题,可以先考虑暴力法验证自己的思路,再试图用更高效的算法(像归并排序)来优化性能,面试官看到你不仅能做,还能优化,肯定会加分的!
对编程、职场感兴趣的同学,大家可以联系我微信:golang404,拉你进入“程序员交流群”。
虎哥作为一名老码农,整理了全网最全《python高级架构师资料合集》。