面试常见算法题

使数组有序的最小交换次数

问题是给出一个数组,然后数组里面的元素可以交换,任意位置都可以交换,然后求使得该数组有序的最小交换次数。

Sample Input 1 
2
4
4 3 2 1
5
1 5 4 3 2

Sample Output 1
2
2

示例输入第一个2是只有2个测试用例,接下来每个测试用例第一个数是4,代表数组长度是4,下一行就是数组的元素(对python来说这个数组长度这个不太需要)。

解法: 目的是去找数组中互换闭包的个数,若数组本来有n个数,现在找到了一个包含x个数的互换闭包,互换闭包的意思就是在闭包内只需要交换x-1次就可以(其实就是最大交换次数),剩下n-x就得交换n-x次,那么总交换次数就是x-1+n-x=n-1次。所以,若找到a个这样的闭包,那么总交换次数就是n-a次。
注意,互换闭包的长度可以为1,也就是若当前位置就是该有的数字,那就不需要交换了。

n = int(input().strip())
for repeat_i in range(n):
    length = int(input().strip())
    line = input()
    str_list = line.split(' ')
    arr = [int(x) for x in str_list]
    # 先排个序,找到每个数字对应的位置
    new_arr = sorted(arr)
    dict_position = {}
    for i in range(len(new_arr)):
        dict_position[new_arr[i]] = i

    print("dict_position", dict_position)
    # 中心思想很简单,就是针对每一个位置上的数,
    # 我假设这个数被换到对应位置上,
    # 现在我看一下对应位置上的数有没有被访问过
    # 如果对应位置上的数没有被访问过,
    # 那我把对应位置上的数再交换到它对应的位置上,
    # 现在我再看看对应位置上的数应该在的位置上那个数有没有被访问过
    res_closure = 0
    flag = [0 for x in arr]
    for i in range(len(arr)):
        if flag[i] == 0:
            print("i",i)
            j = i
            while flag[j] == 0:
                print("j",j)
                flag[j] = 1
                j = dict_position[arr[j]]
            res_closure += 1
    print(len(arr) - res_closure)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章