当前位置: 首页 > 知识库问答 >
问题:

组织K内所有元素所需的最小交换

袁泰平
2023-03-14

我最近遇到了一个编码面试问题,似乎找不到答案。问题是这样的。

给定一个整数数组,编写一个函数,返回组织数组所需的最小交换,以便每个相邻元素的差值小于或等于K。

例如

public static void main(String[] argv) {
    int[] arr1 = new int[]{10, 40, 30, 20};
    int K = 20;
    getMinimumSwap(arr1, K); // should return 1
}

它应该返回1的原因是,通过交换40和30,数组将满足给定的语句,即所有相邻元素之间的间距应在20以内。

我确实试着在谷歌上搜索答案,我想我在其他算法助手网站上找到了一些答案,但无法找到我问题的答案。失败的测试用例有一个数组3,7,2,8,6,4,5,1K=3,它们应该返回2

共有1个答案

堵飞鸿
2023-03-14

我将把它作为一个图形搜索问题来解决。

为了解决这个图搜索问题,我们首先需要定义系统的状态。在这种情况下,状态将是数字的序列。

定义状态后,每个图形搜索问题都可以完成这项工作,但由于您希望交换的数量最少,我们将使用BFS。

为了方便起见,下面用python实现,但也可以用java实现。

首先,我们将编写一个帮助函数,给出一个数字序列,返回该序列中所有可能的1-swap:

def get_swapps(sequence):
    swapps = []
    ii = 0
    jj = 1
    done = False
    while not done:
        temp_seq = sequence.copy()
        temp     = sequence[jj]
        temp_seq[jj] = sequence[ii]
        temp_seq[ii] = temp
        swapps.append(temp_seq)
        if jj < len(sequence)-1:
            jj += 1
        elif ii < len(sequence)-2:
            ii += 1
            jj = ii + 1
        else:
            done = True
    return swapps

请注意,这不是最好的写法,但它确实做到了。

现在我们可以实现如下BFS算法(在这里阅读更多关于BFS和DFS的内容)

def findSwap(sequence, k):
    state_queue = []  # Pending states which have not been explored yet
    visited     = []
    state    = (sequence, 0)  # Starting state, starting sequence and 0 swapps
    min_diff = max([abs(sequence[1:][ii] - sequence[:-1][ii]) for ii in range(len(sequence)-1)])
    found    = True
    while min_diff >= k:
        # saving the visited states
        visited.append(state)
        curr_seq = state[0]
        curr_count = state[1]
        # Getting all swapps possible
        swaps = get_swapps(curr_seq)
        # adding to the queue all the unvisited states
        for next_state in swaps:
            None if any([next_state == visited_state[0] for visited_state in visited]) else state_queue.append((next_state, curr_count+1))
        # popping next state from the queue
        if len(state_queue) > 0:
            state = state_queue.pop(0)
            curr_seq = state[0]
            min_diff = max([abs(curr_seq[1:][ii] - curr_seq[:-1][ii]) for ii in range(len(curr_seq) - 1)])
        else:
            found = False
            break
    if found:
        return state[1]
    else:
        return -1

在每个州,我们:

  1. 生成可能的下一个状态,这是1-交换排列。
  2. 对于每个下一个状态候选,我们检查是否已经访问了该状态,如果没有访问该状态,我们将下一个状态添加到状态队列中。

检查完所有可能的下一个状态后,我们从队列中弹出下一个状态,并检查最大差异。如果最大差值是lees,那么我们就完了。如果队列为空,我们搜索了所有状态空间,但没有找到解决方案,在本例中,我们将返回-1

注意,除了状态之外,我们还携带了元组中从原始状态到该状态的交换次数。

设置测试阵列时,我们得到:

a = [3,7,2,8,6,4,5,1]
print(findSwap(a, 3))  # 2, as expected

 类似资料:
  • 问题内容: 所有特定字母(例如“ A”)都需要替换为所有括号。 例如, 我想将圆括号中的所有“ A”替换为“,以使最终结果如下: 有可能仅在正则表达式中执行此操作吗? 问题答案: 对于这种情况,有一个通用的解决方法-不应存在不平衡/嵌套的括号(按原样)。您寻找在圆括号后没有匹配圆括号的: 现场演示 Python代码:

  • 问题内容: 在n = 5和k = 3的情况下,以下循环将执行此操作 但是效率不高,我想使用Banker的序列来完成,因此先探索单例,然后研究配对,然后研究三元组再停止。 我没有找到一种方法,但是至少此循环应该更有效: 还有:但是k个嵌入式循环看起来很丑 问题答案: 即使k个嵌入式循环看起来很丑,这也应该是最有效的方法

  • 问题内容: 我想编写一个函数,该函数以字母数组作为参数,并选择多个字母。 假设您提供8个字母的数组,并希望从中选择3个字母。然后您将获得: 返回由3个字母组成的数组(或单词)。 问题答案: 格雷码您会遇到的一个问题当然是记忆力,而且很快,您的集合中会有20个元素出现问题-20 C 3 =1140。而且,如果要遍历集合,最好使用修改后的灰色代码算法,因此您不必将所有代码都保存在内存中。这些将根据之前

  • 我看到一个问题,要求它找到所有相邻子阵列的最小值。例如,对于数组A=[1,2,3],答案将是一个包含[1,2,3,1,2,1]的数组B<怎么做- 我所做的是,构建了一个段树,但是它不包含所有连续子数组的最小值。 我也不认为我可以使用“脱钩”,因为我不必在特定长度的子数组中找到最小值。 那么,我如何获得所有连续子阵列(B阵列)的最小值?

  • 问题内容: 我有一组值,并想创建包含2个元素的所有子集的列表。 例如,源集具有以下2个元素的子集: 有没有办法在python中做到这一点? 问题答案: 好像你想要的: 如果要设置,则必须显式转换它们。如果您不介意使用迭代器而不是列表,并且使用的是Python 3,则可以使用: 要一次查看所有结果,可以将的输出传递给。(在Python 2中,的输出自动为列表。) 但是,如果您知道需要列表,则列表理解

  • 问题内容: 给出了长度为 n 的数组。查找子数组元素的乘积之和。 说明 数组 A* = 长度 3的 [2,3,4] 。 * 长度为 2的 子数组= [2,3],[3,4],[2,4] [2,3] 中元素的乘积= 6 [3,4] 中元素的乘积= 12 [2,4] 中元素的乘积= 8 长度 2 = 6 + 12 + 8 = 26的子数组的总和 同样,对于长度 3 ,Sum = 24 因此,乘积以模 1