给定一个非负整数数组 nums ,你最初位于数组的 第一个下标 。

数组中的每个元素代表你在该位置可以跳跃的最大长度。

判断你是否能够到达最后一个下标。

示例 1: 输入:nums = [2,3,1,1,4] 输出:true 解释:可以先跳 1 步,从下标 0 到达下标 1, 然后再从下标 1 跳 3 步到达最后一个下标。

示例 2: 输入:nums = [3,2,1,0,4] 输出:falsea 解释:无论怎样,总会到达下标为 3 的位置。但该下标的最大跳跃长度是 0 , 所以永远不可能到达最后一个下标。

题解

贪心算法(英语:greedy algorithm),又称贪婪算法,是一种在每一步选择中都采取在当前状态下最好或最优(即最有利)的选择,从而希望导致结果是最好或最优的算法

使用条件

利用贪心法求解的问题应具备如下2个特征 。

1、贪心选择性质

一个问题的整体最优解可通过一系列局部的最优解的选择达到,并且每次的选择可以依赖以前作出的选择,但不依赖于后面要作出的选择。这就是贪心选择性质。对于一个具体问题,要确定它是否具有贪心选择性质,必须证明每一步所作的贪心选择最终导致问题的整体最优解 。

2、最优子结构性质

当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。问题的最优子结构性质是该问题可用贪心法求解的关键所在。在实际应用中,至于什么问题具有什么样的贪心选择性质是不确定的,需要具体问题具体分析 。

代码示例

<template>
  <div class="flex flex-col h-screen w-full item-center justify-center">
    <div class="flex justify-center">
      <div
        class="rounded cursor-pointer bg-blue-400 text-hex-fff text-center p-3 w-30"
        @click="jump">
        start jump
      </div>
      <div
        class="rounded cursor-pointer bg-blue-400 text-hex-fff text-center ml-4 p-3 w-30"
        @click="resetJump">
        reset jump
      </div>
    </div>
    <div class="my-8 text-center">可跳步数:{{ stepNumber }}</div>
    <div class="flex items-center justify-center">
      <div
        v-for="(item, index) of list"
        :key="item"
        class="rounded cursor-pointer bg-gray-100 h-20 text-center mr-2 transition leading-20 w-20 relative"
        :class="{
          'shadow bg-hex-fff': active === index,
          'pointer-events-none': index > active + stepNumber,
          '!bg-gray-300': active + stepNumber >= index && index > active,
        }"
        @click="onItemClick(item, index)">
        {{ item }}

        <div
          v-show="maxStep > index - 1"
          class="h-5 text-center top-0 right-0 text-green-500 leading-5 w-5 absolute">
          <van-icon name="success" />
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
const list = ref([2, 3, 1, 2, 4, 1, 3, 6, 0, 1, 3])
const active = ref(0)

const stepNumber = computed(() => list.value[active.value])

const isJumping = ref(false)
const maxStep = ref(0)

function onItemClick(item: number, index: number) {
  maxStep.value = Math.max(maxStep.value, item + index)
  active.value = index

  if (maxStep.value >= list.value.length - 1) {
    console.log('canJump')
    Toast('can Jump')
  }
}

async function jump() {
  if (isJumping.value) return
  isJumping.value = true

  const len = list.value.length
  maxStep.value = 0

  for (let index = 0; index < len; index++) {
    if (maxStep.value >= index) {
      maxStep.value = Math.max(maxStep.value, list.value[index] + index)
      active.value = index

      if (maxStep.value >= len - 1) {
        console.log('canJump')
        Toast('can Jump')
        isJumping.value = false
        return
      }
      await sleep(1)
    }
  }

  Toast('can’t Jump')
  isJumping.value = false
  return false
}

function resetJump() {
  maxStep.value = list.value[0]
  active.value = 0
}

function sleep(timer = 1) {
  return new Promise<void>((resolve, reject) => {
    setTimeout(() => {
      resolve()
    }, 1000 * timer)
  })
}

onBeforeMount(resetJump)
</script>