(C卷,100分)- 约瑟夫问题(Java & JS & Python & C)

题目描述

输入一个由随机数组成的数列(数列中每个数均是大于 0 的整数,长度已知),和初始计数值 m。

从数列首位置开始计数,计数到 m 后,将数列该位置数值替换计数值 m,

并将数列该位置数值出列,然后从下一位置从新开始计数,直到数列所有数值出列为止。

如果计数到达数列尾段,则返回数列首位置继续计数。

请编程实现上述计数过程,同时输出数值出列的顺序。

比如:输入的随机数列为:3,1,2,4,初始计数值 m=7,从数列首位置开始计数(数值 3 所在位置)

第一轮计数出列数字为 2,计数值更新 m=2,出列后数列为 3,1,4,从数值 4 所在位置从新开始计数

第二轮计数出列数字为 3,计数值更新 m=3,出列后数列为 1,4,从数值 1 所在位置开始计数

第三轮计数出列数字为 1,计数值更新 m=1,出列后数列为 4,从数值 4 所在位置开始计数

最后一轮计数出列数字为 4,计数过程完成。输出数值出列顺序为:2,3,1,4。

要求实现函数:

void array_iterate(int len, int input_array[], int m, int output_array[])

输入描述

 int len:输入数列的长度; int intput_array[]:输入的初始数列 int m:初始计数值

输出描述

 int output_array[]:输出的数值出列顺序

用例

输入

3,1,2,4
4
7

输出 2,3,1,4
说明

输入

第一行是初始数列intput_array

第二行是初始数列的长度len

第三行是初始计数值m

输出

数值出列顺序

题目解析

本题就是约瑟夫环的变种题。

约瑟夫环的解题有多种方式,比较容易理解和实现的可以使用双端队列。

即intput_array当成双端队列,从队头取出元素,判断此时计数是否为m:

  • 若是,则将取出的元素加入output_arr,并将取出的元素的值赋值给m,然后len–,计数重置为1
  • 若不是,则将取出的元素塞回intput_array的队尾,仅计数++

但是本题JS是基于数组实现的双端队列,因此每次头部元素出队,都意味着一次O(n)复杂度的数组元素前移一位操作,这是非常影响性能的。

对于Java,Python都有内置的双端队列结构,因此可以直接复用,对于C,可以自己实现双端队列结构。

因此JS语言我们可以选择循环链表来模拟约瑟夫环。

循环链表本身就实现了环形结构,其head.prev = tail,tail.next = head。

且循环链表删除节点的复杂度是O(1)。

唯一的遗憾是,JS没有原生的循环链表结构,我们需要自己实现。但是我们只需要实现最简单的循环链表即可,即只实现循环链表的尾部新增节点操作即可。而删除操作可以在实际业务中完成。

JavaScript算法源码

双端队列

/* JavaScript Node ACM模式 控制台输入获取 */
const readline = require("readline");

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

const lines = [];
rl.on("line", (line) => {
  lines.push(line);

  if (lines.length === 3) {
    const input_arr = lines[0].split(",");
    const len = lines[1];
    const m = lines[2];

    const output_arr = [];
    array_iterate(len, input_arr, m, output_arr);
    console.log(output_arr.join(","));
    lines.length = 0;
  }
});

function array_iterate(len, input_arr, m, output_arr) {
  let i = 1;
  while (len > 0) {
    const out = input_arr.shift();
    if (i == m) {
      output_arr.push(out);
      m = out;
      i = 1;
      len--;
    } else {
      input_arr.push(out);
      i++;
    }
  }
}

循环链表

/* JavaScript Node ACM模式 控制台输入获取 */
const readline = require("readline");

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

const lines = [];
rl.on("line", (line) => {
  lines.push(line);

  if (lines.length === 3) {
    const input_arr = lines[0].split(",");
    const len = lines[1];
    const m = lines[2];

    const output_arr = [];
    array_iterate(len, input_arr, m, output_arr);
    console.log(output_arr.join(","));
    lines.length = 0;
  }
});

function array_iterate(len, input_arr, m, output_arr) {
  const cll = new CircularLinkedList();
  cll.init(input_arr);

  let cur = cll.head;
  let i = 1;
  while (cll.size) {
    if (i == m) {
      const pre = cur.prev;
      const nxt = cur.next;

      pre.next = nxt;
      nxt.prev = pre;

      m = cur.val;
      output_arr.push(m);
      cur.next = cur.prev = null;

      cur = nxt;

      i = 1;
      cll.size--;
    } else {
      i++;
      cur = cur.next;
    }
  }
}

class Node {
  constructor(val) {
    this.val = val;
    this.next = null;
    this.prev = null;
  }
}

class CircularLinkedList {
  constructor() {
    this.head = null;
    this.tail = null;
    this.size = 0;
  }

  append(val) {
    const node = new Node(val);

    if (this.size) {
      this.tail.next = node;
      node.prev = this.tail;
      this.tail = node;
    } else {
      this.head = node;
      this.tail = node;
    }

    this.head.prev = this.tail;
    this.tail.next = this.head;

    this.size++;
  }

  init(arr) {
    arr.forEach((val) => {
      this.append(val);
    });
  }
}

Java算法源码

Java可以使用LinkedList模拟双端队列

import java.util.*;

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

    Integer[] input_arr =
        Arrays.stream(sc.nextLine().split(",")).map(Integer::parseInt).toArray(Integer[]::new);

    int len = Integer.parseInt(sc.nextLine());

    int m = Integer.parseInt(sc.nextLine());

    System.out.println(getResult(input_arr, len, m));
  }

  public static String getResult(Integer[] input_arr, int len, int m) {
    LinkedList<Integer> dq = new LinkedList<>(Arrays.asList(input_arr));

    ArrayList<Integer> output_arr = new ArrayList<>();

    int i = 1;
    while (len > 0) {
      Integer out = dq.removeFirst();

      if (i == m) {
        output_arr.add(out);
        m = out;
        i = 1;
        len--;
      } else {
        dq.add(out);
        i++;
      }
    }

    StringJoiner sj = new StringJoiner(",");
    for (Integer ele : output_arr) {
      sj.add(ele + "");
    }
    return sj.toString();
  }
}

Python算法源码

from collections import deque

# 输入获取
input_arr = deque(list(map(int, input().split(","))))
length = int(input())
m = int(input())


# 算法入口
def getResult():
    global input_arr
    global length
    global m

    output_arr = []

    i = 1
    while length > 0:
        out = input_arr.popleft()
        if i == m:
            output_arr.append(out)
            m = out
            i = 1
            length -= 1
        else:
            input_arr.append(out)
            i += 1

    return ",".join(map(str, output_arr))


# 算法调用
print(getResult())

C算法源码

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

typedef struct ListNode {
    int ele;
    struct ListNode* next;
} ListNode;

typedef struct {
    int size;
    ListNode* head;
    ListNode* tail;
} LinkedList;

LinkedList* new_LinkedList();
void addLast_LinkedList(LinkedList* link, int ele);
int removeFirst(LinkedList* link);

int main() {
    LinkedList* dq = new_LinkedList();

    int num;
    while(scanf("%d", &num)) {
        addLast_LinkedList(dq,num);
        if(getchar() != ',') break;
    }

    int len;
    scanf("%d", &len);

    int m;
    scanf("%d", &m);

    LinkedList* output_arr = new_LinkedList();

    int i = 1;
    while(len > 0) {
        int out = removeFirst(dq);

        if(i == m) {
            addLast_LinkedList(output_arr,out);
            m = out;
            i = 1;
            len--;
        } else {
            addLast_LinkedList(dq,out);
            i++;
        }
    }

    char res[100000];

    ListNode* cur = output_arr->head;
    while(cur != NULL) {
        char tmp[10];
        sprintf(tmp, "%d", cur->ele);
        strcat(res, tmp);

        cur = cur->next;

        if(cur != NULL) {
            strcat(res, ",");
        }
    }

    puts(res);

    return 0;
}

LinkedList* new_LinkedList() {
    LinkedList* link = (LinkedList*) malloc(sizeof(LinkedList));

    link->size = 0;
    link->head = NULL;
    link->tail = NULL;

    return link;
}

void addLast_LinkedList(LinkedList* link, int ele) {
    ListNode* node = (ListNode*) malloc(sizeof(ListNode));

    node->ele = ele;
    node->next = NULL;

    if(link->size == 0) {
        link->head = node;
        link->tail = node;
    } else {
        link->tail->next = node;
        link->tail = node;
    }

    link->size++;
}

int removeFirst(LinkedList* link) {
    if(link->size == 0) exit(-1);

    ListNode* removed = link->head;

    if(link->size == 1) {
        link->head = NULL;
        link->tail = NULL;
    } else {
        link->head = link->head->next;
    }

    link->size--;

    int res = removed->ele;

    free(removed);

    return res;
}

 

免责声明:

1、IT资源小站为非营利性网站,全站所有资料仅供网友个人学习使用,禁止商用
2、本站所有文档、视频、书籍等资料均由网友分享,本站只负责收集不承担任何技术及版权问题
3、如本帖侵犯到任何版权问题,请立即告知本站,本站将及时予与删除下载链接并致以最深的歉意
4、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责
5、一经注册为本站会员,一律视为同意网站规定,本站管理员及版主有权禁止违规用户
6、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者和IT资源小站的同意
7、IT资源小站管理员和版主有权不事先通知发贴者而删除本文

0

评论0

站点公告

没有账号?注册  忘记密码?