欢迎光临
我们一直在努力

2026 华为OD机试真题 新系统 9月20号 【递增差排列】多语言题解

递增差排列(Java/Py/C/C++/Js/Go)题解

华为OD机试真题 新系统 华为OD上机考试真题新系统 9月20号 200分题型

华为OD机试新系统真题目录点击查看: 华为OD机试新系统真题题库目录|机考题库 + 算法考点详解

题目内容

给定两个正整数

n

n

n

k

k

k(其中

1

k

n

8

1 \\leq k \\leq n \\leq 8

1kn8),从

[

1

,

n

]

[1, n]

[1,n] 中选取

k

k

k 个元素,排成长度为

k

k

k 的有序数组,按如下条件筛选排列组合后返回:

  • 数组中的元素取自整数

    [

    1

    ,

    n

    ]

    [1, n]

    [1,n],且互不相同。

  • 对于数组中任意连续三个元素

    a

    [

    i

    ]

    ,

    a

    [

    i

    +

    1

    ]

    ,

    a

    [

    i

    +

    2

    ]

    a[i], a[i+1], a[i+2]

    a[i],a[i+1],a[i+2](即长度至少为

    3

    3

    3 时),必须满足:

    abs

    (

    a

    [

    i

    ]

    a

    [

    i

    +

    1

    ]

    )

    <

    abs

    (

    a

    [

    i

    +

    1

    ]

    a

    [

    i

    +

    2

    ]

    )

    \\text{abs}(a[i] – a[i+1]) < \\text{abs}(a[i+1] – a[i+2])

    abs(a[i]a[i+1])<abs(a[i+1]a[i+2])

  • k

    <

    3

    k < 3

    k<3 时,不存在需要检查的连续三个元素,条件

    2

    2

    2 视为自动满足。

  • 请按字典序升序返回所有可能的排列。如果不存在,返回空列表。

    输入描述

    两个正整数,分别代表

    n

    n

    n

    k

    k

    k

    输出描述

    一个二维数组,包含所有符合条件的排列。

    样例1

    输入

    3 3

    输出

    2 1 3
    2 3 1

    说明

    • [

      1

      ,

      2

      ,

      3

      ]

      [1,2,3]

      [1,2,3]:差值为

      1

      2

      =

      1

      |1-2|=1

      ∣12∣=1

      2

      3

      =

      1

      |2-3|=1

      ∣23∣=1,不满足

      1

      <

      1

      1 < 1

      1<1(严格递增失败)。

    • [

      2

      ,

      1

      ,

      3

      ]

      [2,1,3]

      [2,1,3]:差值为

      1

      ,

      2

      1, 2

      1,2,满足

      1

      <

      2

      1 < 2

      1<2

    • [

      2

      ,

      3

      ,

      1

      ]

      [2,3,1]

      [2,3,1]:差值为

      1

      ,

      2

      1, 2

      1,2,满足

      1

      <

      2

      1 < 2

      1<2

    • 其余排列均不满足条件。

    样例2

    输入

    4 2

    输出

    1 2
    1 3
    1 4
    2 1
    2 3
    2 4
    3 1
    3 2
    3 4
    4 1
    4 2
    4 3

    说明 因为

    k

    =

    2

    k=2

    k=2,序列中只有一对差值,没有后一对进行比较,所以任意两个不同的数字都算满足条件(按字典序输出全部排列)。

    解题思路

    思路:递归回溯

    • 本题题目特征以及数据范围1 <= k <= n <=8决定可以使用递归回溯进行解决。利用递归回溯算法从[1,n]枚举选出k个互异整数并满足相邻绝对值差严格递增的合法排列。
    • 递归回溯过程中使用vis数组表示数字是否已选择?使用path存储之前已经枚举确定合法序列部分,使用ans保存所有合法序列
    • 每一层递归中,将 i 按照1-n顺序尝试放置(可以保证生成序列天然满足升序),并进行如下判断
      • vis[i] == true: 已被使用,不能选择直接跳过。
      • 检查相邻差绝对值是否满足递增:
        • path.size() <= 1: 直接加入当前数字,更新vis[i] = true, path.push_back(i), 往下递归。
        • path.size() > 1: 需要检查当前数字加入后,后三个数是否满足绝对值之差严格递增。满足情况下 更新vis[i] = true, path.push_back(i), 往下递归。
    • 递归结束条件为path.size() == k, 然后进行回溯,搜索不同路径。

    C++

    #include<bits/stdc++.h>
    #include <vector>
    using namespace std;

    void dfs(int n, int k, vector<bool>& vis, vector<int>& path, vector<vector<int>>& ans) {
    int m = path.size();
    if (m == k) {
    ans.push_back(path);
    return;
    }
    // 从小到大枚举,生成结果天然满足字典序升序规则
    for (int i = 1; i <= n; i++) {
    // 不能选择重复元素
    if (vis[i]) {
    continue;
    }
    // 加入当前少于3个,无需检查
    if (m <= 1) {
    path.push_back(i);
    vis[i] = true;
    dfs(n, k, vis, path, ans);
    vis[i] = false;
    path.pop_back();
    // 加入当前数达到3个,检查合规性
    } else {
    int lastOne = path[m 1];
    int lastTwo = path[m 2];
    if (abs(lastTwo lastOne) < abs(lastOne i)) {
    path.push_back(i);
    vis[i] = true;
    dfs(n, k, vis, path, ans);
    vis[i] = false;
    path.pop_back();
    }
    }
    }
    }

    vector<vector<int>> solve(int n, int k) {
    vector<vector<int>> ans;
    vector<bool> vis(n + 1, false);
    vector<int> path;
    dfs(n, k, vis, path, ans);
    return ans;
    }

    int main() {
    int n, k;
    cin >> n >> k;
    vector<vector<int>> ans = solve(n, k);
    for (int i = 0; i < ans.size(); i++) {
    for (int j = 0; j < ans[i].size(); j++) {
    if (j > 0) {
    cout << " ";
    }
    cout << ans[i][j];
    }
    cout << endl;
    }
    }

    JAVA

    import java.util.*;

    public class Main {

    static void dfs(int n, int k, boolean[] vis, List<Integer> path, List<List<Integer>> ans) {
    int m = path.size();

    if (m == k) {
    ans.add(new ArrayList<>(path));
    return;
    }

    // 从小到大枚举,生成结果天然满足字典序升序规则
    for (int i = 1; i <= n; i++) {
    // 不能选择重复元素
    if (vis[i]) {
    continue;
    }

    // 加入当前少于3个,无需检查
    if (m <= 1) {
    path.add(i);
    vis[i] = true;
    dfs(n, k, vis, path, ans);
    vis[i] = false;
    path.remove(path.size() 1);

    // 加入当前数达到3个,检查合规性
    } else {
    int lastOne = path.get(m 1);
    int lastTwo = path.get(m 2);

    if (Math.abs(lastTwo lastOne) < Math.abs(lastOne i)) {
    path.add(i);
    vis[i] = true;
    dfs(n, k, vis, path, ans);
    vis[i] = false;
    path.remove(path.size() 1);
    }
    }
    }
    }

    static List<List<Integer>> solve(int n, int k) {
    List<List<Integer>> ans = new ArrayList<>();
    boolean[] vis = new boolean[n + 1];
    List<Integer> path = new ArrayList<>();

    dfs(n, k, vis, path, ans);

    return ans;
    }

    public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);

    int n = sc.nextInt();
    int k = sc.nextInt();

    List<List<Integer>> ans = solve(n, k);

    for (List<Integer> row : ans) {
    for (int j = 0; j < row.size(); j++) {
    if (j > 0) {
    System.out.print(" ");
    }
    System.out.print(row.get(j));
    }
    System.out.println();
    }
    }
    }

    Python

    def dfs(n, k, vis, path, ans):
    m = len(path)

    if m == k:
    ans.append(path[:])
    return

    # 从小到大枚举,生成结果天然满足字典序升序规则
    for i in range(1, n + 1):
    # 不能选择重复元素
    if vis[i]:
    continue

    # 加入当前少于3个,无需检查
    if m <= 1:
    path.append(i)
    vis[i] = True
    dfs(n, k, vis, path, ans)
    vis[i] = False
    path.pop()

    # 加入当前数达到3个,检查合规性
    else:
    last_one = path[m 1]
    last_two = path[m 2]

    if abs(last_two last_one) < abs(last_one i):
    path.append(i)
    vis[i] = True
    dfs(n, k, vis, path, ans)
    vis[i] = False
    path.pop()

    def solve(n, k):
    ans = []
    vis = [False] * (n + 1)
    path = []

    dfs(n, k, vis, path, ans)

    return ans

    n, k = map(int, input().split())

    ans = solve(n, k)

    for row in ans:
    print(" ".join(map(str, row)))

    JavaScript

    const readline = require("readline");

    const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
    });

    rl.on("line", line => {
    const [n, k] = line.trim().split(/\\s+/).map(Number);

    function dfs(n, k, vis, path, ans) {
    const m = path.length;

    if (m === k) {
    ans.push([path]);
    return;
    }

    // 从小到大枚举,生成结果天然满足字典序升序规则
    for (let i = 1; i <= n; i++) {
    // 不能选择重复元素
    if (vis[i]) {
    continue;
    }

    // 加入当前少于3个,无需检查
    if (m <= 1) {
    path.push(i);
    vis[i] = true;
    dfs(n, k, vis, path, ans);
    vis[i] = false;
    path.pop();

    // 加入当前数达到3个,检查合规性
    } else {
    const lastOne = path[m 1];
    const lastTwo = path[m 2];

    if (Math.abs(lastTwo lastOne) < Math.abs(lastOne i)) {
    path.push(i);
    vis[i] = true;
    dfs(n, k, vis, path, ans);
    vis[i] = false;
    path.pop();
    }
    }
    }
    }

    function solve(n, k) {
    const ans = [];
    const vis = new Array(n + 1).fill(false);
    const path = [];

    dfs(n, k, vis, path, ans);

    return ans;
    }

    const ans = solve(n, k);

    for (const row of ans) {
    console.log(row.join(" "));
    }

    rl.close();
    });

    Go

    package main

    import (
    "bufio"
    "fmt"
    "math"
    "os"
    )

    func dfs(n, k int, vis []bool, path []int, ans *[][]int) {
    m := len(path)

    if m == k {
    temp := make([]int, len(path))
    copy(temp, path)
    *ans = append(*ans, temp)
    return
    }

    // 从小到大枚举,生成结果天然满足字典序升序规则
    for i := 1; i <= n; i++ {
    // 不能选择重复元素
    if vis[i] {
    continue
    }

    // 加入当前少于3个,无需检查
    if m <= 1 {
    path = append(path, i)
    vis[i] = true
    dfs(n, k, vis, path, ans)
    vis[i] = false
    path = path[:len(path)1]

    // 加入当前数达到3个,检查合规性
    } else {
    lastOne := path[m1]
    lastTwo := path[m2]

    if math.Abs(float64(lastTwolastOne)) < math.Abs(float64(lastOnei)) {
    path = append(path, i)
    vis[i] = true
    dfs(n, k, vis, path, ans)
    vis[i] = false
    path = path[:len(path)1]
    }
    }
    }
    }

    func solve(n, k int) [][]int {
    ans := make([][]int, 0)
    vis := make([]bool, n+1)
    path := make([]int, 0)

    dfs(n, k, vis, path, &ans)

    return ans
    }

    func main() {
    in := bufio.NewReader(os.Stdin)
    out := bufio.NewWriter(os.Stdout)
    defer out.Flush()

    var n, k int
    fmt.Fscan(in, &n, &k)

    ans := solve(n, k)

    for _, row := range ans {
    for j, value := range row {
    if j > 0 {
    fmt.Fprint(out, " ")
    }
    fmt.Fprint(out, value)
    }
    fmt.Fprintln(out)
    }
    }

    C语言

    #include <stdio.h>
    #include <stdlib.h>
    #include <stdbool.h>

    void dfs(int n, int k, bool vis[], int path[], int m,
    int ans[][10], int *ansSize) {
    if (m == k) {
    for (int i = 0; i < k; i++) {
    ans[*ansSize][i] = path[i];
    }
    (*ansSize)++;
    return;
    }

    // 从小到大枚举,生成结果天然满足字典序升序规则
    for (int i = 1; i <= n; i++) {
    // 不能选择重复元素
    if (vis[i]) {
    continue;
    }

    // 加入当前少于3个,无需检查
    if (m <= 1) {
    path[m] = i;
    vis[i] = true;

    dfs(n, k, vis, path, m + 1, ans, ansSize);

    vis[i] = false;

    // 加入当前数达到3个,检查合规性
    } else {
    int lastOne = path[m 1];
    int lastTwo = path[m 2];

    if (abs(lastTwo lastOne) < abs(lastOne i)) {
    path[m] = i;
    vis[i] = true;

    dfs(n, k, vis, path, m + 1, ans, ansSize);

    vis[i] = false;
    }
    }
    }
    }

    void solve(int n, int k, int ans[][10], int *ansSize) {
    bool vis[105] = {false};
    int path[10];

    dfs(n, k, vis, path, 0, ans, ansSize);
    }

    int main() {
    int n, k;
    scanf("%d %d", &n, &k);

    int ans[100000][10];
    int ansSize = 0;

    solve(n, k, ans, &ansSize);

    for (int i = 0; i < ansSize; i++) {
    for (int j = 0; j < k; j++) {
    if (j > 0) {
    printf(" ");
    }
    printf("%d", ans[i][j]);
    }
    printf("\\n");
    }

    return 0;
    }

    赞(0)
    未经允许不得转载:171主机测评 » 2026 华为OD机试真题 新系统 9月20号 【递增差排列】多语言题解
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址