剑指offer_20230723

发布时间 2023-07-24 11:22:06作者: XCCX0824

剑指 Offer 50. 第一个只出现一次的字符

题目说明

在字符串 s 中找出第一个只出现一次的字符。如果没有,返回一个单空格。 s 只包含小写字母。

解题思路1:HashMap

使用传统的HashMap,对整一个数组进行遍历,更新记录每个字母的出现次数。在遍历结束之后重新遍历一遍数组,获取每个字母对应的取值。技巧是可以设置成为<Integer, Boolean>类型,出现第一次置为true,第二次乃至更多次都置为false

解题思路2:new int[26]

因为题目说明只有26个小写字母,那么我们可以用new int[26]的数组来当作HashMap使用,此后思路和思路1基本相同。但是这里不能用Boolean类型数组,因为即使字母没出现也要赋予一个值,那么就有三种状态了,用Boolean不再合适

解题思路3:LinkedHashMap

在Java中,使用LinkedHashMap可以实现有序哈希表

这道题目很明显对于顺序有一个要求,因此我们可以用LinkedHashMap来存储,这样在记录了次数的同时也维护了顺序性。此后就不用再去遍历一遍初始数组而是遍历LinkedHashMap来获取答案即可

剑指 Offer 11. 旋转数组的最小数字(第二次啦)

题目说明

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。

给你一个可能存在 重复 元素值的数组 numbers ,它原来是一个升序排列的数组,并按上述情形进行了一次旋转。请返回旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一次旋转,该数组的最小值为 1。

解题思路:二分查找

fig1

考虑数组中的最后一个元素x:在最小值右侧的元素都一定小于等于x,在最小值左侧的元素一定都大于等于x,可以利用该性质通过二分查找找出。

我们通过right处的值和mid处的值进行比较。可能有三种情况发生:

  1. numbers[right] > numbers[mid]:说明从mid到right是有序的,最小值有可能出现在mid处,将right更新为mid
  2. numbers[right] < numbers[mid]:说明波谷出现在mid + 1到right这一段,将left更新为mid
  3. numbers[right] < numbers[mid]:可能出现如下图所示的情况,此时无法确定波谷在mid到right这一段或者left到mid这一段,但可以肯定的是一定不会出现在high的位置,所以令high左移一步缩小范围

fig4

当循环结束时left=high,返回该位置的数字即可

剑指 Offer 53 - II. 0~n-1中缺失的数字

题目说明

一个长度为n-1的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围0~n-1之内。在范围0~n-1内的n个数字中有且只有一个数字不在该数组中,请找出这个数字。

解题思路

nums[i]i有两种情况,分别是相等和nums[i] > i,前者说明i及左边没问题,后者说明i右边没问题(但i可能是有问题的)

image-20230724111224054

跳出时,变量ij 分别指向 “右子数组的首位元素” 和 “左子数组的末位元素” 。因此返回i即可。