(C卷,100分)- 找朋友(Java & JS & Python & C)

题目描述

在学校中,N个小朋友站成一队, 第i个小朋友的身高为height[i],

第i个小朋友可以看到的第一个比自己身高更高的小朋友j,那么j是i的好朋友(要求j > i)。

请重新生成一个列表,对应位置的输出是每个小朋友的好朋友位置,如果没有看到好朋友,请在该位置用0代替。

小朋友人数范围是 [0, 40000]。

输入描述

第一行输入N,N表示有N个小朋友

第二行输入N个小朋友的身高height[i],都是整数

输出描述

输出N个小朋友的好朋友的位置

用例

输入 2
100 95
输出 0 0
说明

第一个小朋友身高100,站在队尾位置,向队首看,没有比他身高高的小朋友,所以输出第一个值为0。

第二个小朋友站在队首,前面也没有比他身高高的小朋友,所以输出第二个值为0。

输入 8
123 124 125 121 119 122 126 123
输出 1 2 6 5 5 6 0 0
说明 123的好朋友是1位置上的124
124的好朋友是2位置上的125
125的好朋友是6位置上的126
以此类推

题目解析

感觉很简单,直接双重for,逻辑如下

/* 记录前面出现的第一个比自己高的人的序号 */
function getHigherIndex(arr) {
  let higherIndex = arr.slice().fill(0);
  for (let i = 0; i < arr.length - 1; i++) {
    for (let j = i + 1; j < arr.length; j++) {
      if (arr[j] > arr[i]) {
        higherIndex[i] = j;
        break;
      }
    }
  }
  return higherIndex;
}

但是时间复杂度是O(n^2)。那么是不是有优化的可能呢?

下面图示中,我们蓝色的是i指针,橙色的是j指针,我么们可以发现j指针的扫描过程存在重复,比如:

  • i=2时,j从121扫描到了126,将扫描过程中j指向的每一个数都和i指向的125进行了比较。
  • i=3时,j又扫描了一遍119,122;
  • i=4时,j又扫描了一遍122
  • i=5时,j又扫描了一遍126

那么如何才能避免重复扫描呢?

 此时我们可以利用栈结构

for循环遍历输入数组的每一个元素,并将遍历出来的 [元素值,索引位置] 尝试压入stack栈中。

如果栈顶没有有元素,则直接压入。

如果栈顶有元素,比如下面图示情况,则比较遍历出来的元素 124 和 stack栈顶元素 123的大小,如果遍历元素值较大,

 则将124的索引位置录入 res[123的索引位置],并将栈顶123弹栈后,压入124

下面操作同理 

 如果遍历的元素值小于栈顶的元素值,则继续下次遍历,如下面例子121小于125,则正常压入后,继续下次遍历

如果遍历的元素122比栈顶元素119大,则栈顶元素119弹栈 

 如果栈顶还有元素,如121

则此时遍历的元素122不执行压入,而是继续和栈顶元素121比较

直到遍历的元素122遇到栈顶元素比自己大时,才执行压入 

 

 这种栈操作的好处,可以避免重复的j指针扫描。

Java算法源码

import java.util.LinkedList;
import java.util.Scanner;
import java.util.StringJoiner;

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

    int n = sc.nextInt();

    int[] arr = new int[n];
    for (int i = 0; i < n; i++) arr[i] = sc.nextInt();

    System.out.println(getResult(arr));
  }

  public static String getResult(int[] arr) {
    LinkedList<int[]> stack = new LinkedList<>();

    int len = arr.length;
    int[] res = new int[len];

    for (int i = 0; i < len; i++) {
      int ele = arr[i];

      while (true) {
        if (stack.size() == 0) {
          stack.add(new int[] {ele, i});
          break;
        }

        int[] peek = stack.getLast();
        int peekEle = peek[0];
        int peekIndex = peek[1];

        if (ele > peekEle) {
          res[peekIndex] = i;
          stack.removeLast();
        } else {
          stack.add(new int[] {ele, i});
          break;
        }
      }
    }

    StringJoiner sj = new StringJoiner(" ");
    for (int v : res) {
      sj.add(v + "");
    }

    return sj.toString();
  }
}

JS算法源码

/* 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 === 2) {
    let n = lines[0];
    let arr = lines[1]
      .split(" ")
      .slice(0, n)
      .map((ele) => parseInt(ele));

    console.log(getHigherIndex(arr).join(" "));

    lines.length = 0;
  }
});

/* 记录第一眼看到比自己高的的人的序号 */
function getHigherIndex(arr) {
  let stack = [];

  let len = arr.length;
  let res = new Array(len).fill(0);

  for (let i = 0; i < len; i++) {
    let ele = arr[i];
    let index = i;

    while (true) {
      if (stack.length === 0) {
        stack.push([ele, index]);
        break;
      }

      let [peekEle, peekIndex] = stack[stack.length - 1];

      if (ele > peekEle) {
        res[peekIndex] = index;
        stack.pop();
      } else {
        stack.push([ele, index]);
        break;
      }
    }
  }

  return res;
}

Python算法源码

# 输入获取
n = int(input())
arr = list(map(int, input().split()))


# 算法入口
def getResult():
    stack = []

    res = [0]*(len(arr))

    for i in range(len(arr)):
        ele = arr[i]

        while True:
            if len(stack) == 0:
                stack.append([ele, i])
                break

            peekEle, peekIndex = stack[-1]

            if ele > peekEle:
                res[peekIndex] = i
                stack.pop()
            else:
                stack.append([ele, i])
                break

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


# 算法调用
print(getResult())

C算法源码

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

#define MAX_SIZE 40000

int stack[MAX_SIZE][2];
int stack_size = 0;

char res[MAX_SIZE * 2];

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

    int heights[MAX_SIZE];
    int heights_size = 0;

    for (int i = 0; i < n; i++) {
        scanf("%d", &heights[heights_size++]);
    }

    int nextHigher[MAX_SIZE] = {0};

    for (int i = 0; i < n; i++) {
        int h = heights[i];

        while (1) {
            if (stack_size == 0) {
                stack[stack_size][0] = h;
                stack[stack_size][1] = i;
                stack_size++;
                break;
            }

            int peekH = stack[stack_size - 1][0];
            int peekI = stack[stack_size - 1][1];

            if (h > peekH) {
                nextHigher[peekI] = i;
                stack_size--;
            } else {
                stack[stack_size][0] = h;
                stack[stack_size][1] = i;
                stack_size++;
                break;
            }
        }
    }

    for (int i = 0; i < heights_size; i++) {
        char tmp[5];
        sprintf(tmp, "%d", nextHigher[i]);
        strcat(res, tmp);
        strcat(res, " ");
    }

    res[strlen(res) - 1] = '';

    puts(res);

    return 0;
}

免责声明:

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

0

评论0

站点公告

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