# The weight of the last stone

Hi, everyone, I’m Zhang Xiaozhu. Welcome to the special article of the “baby can understand” series – the official activity “30 day leetcoding challenge”.

Here is the question of April 12, and also the 1046 question in the list of questions – “the weight of the last stone”

## Title Description

There was a pile of stones, and the weight of each stone was a positive integer.

Each round, choose two pieces**Heaviest**Stones, and then smash them together. Suppose the weights of the stones are `x`

and `y`

, and `x`

<= `y`

。 Then the possible results of crushing are as follows:

- If
`x == y`

Then both stones will be completely crushed; - If
`x != y`

, then the weight is`x`

The stone will be completely crushed, and the weight is`y`

The new weight of the stone is`y-x`

。

In the end, there will be only one stone left at most. Returns the weight of this stone. If there are no stones left, go back`0`

。

Example:

```
Input: [2,7,4,1,8,1]
Output: 1
Explanation:
First select 7 and 8 to get 1, so the array is converted to [2,4,1,1,1],
Then select 2 and 4 to get 2, so the array is converted to [2,1,1,1],
Then 2 and 1 get 1, so the array is converted to [1,1,1],
Finally, select 1 and 1, get 0, and finally convert the array to [1], which is the weight of the last remaining stone.
```

Tips:

`1 <= stones.length <= 30`

`1 <= stones[i] <= 1000`

## Official difficulty

EASY

## Solution ideas

It seems that the description is quite long, but it is actually a small game in which large values offset each other in turn to find the last remaining. Piggy didn’t think of any mathematical way, so let’s find the final result according to the game process.

### Direct scheme

Since the numbers are out of order, let’s sort them first. Then, according to the game flow, offset the two maximum values. If there is margin, put it in the appropriate position by inserting and sorting. In this way, 0 or 1 numbers remain until the end, and the result is obtained.

The specific codes are as follows:

```
const lastStoneWeight = stones => {
stones.sort((a, b) => a - b);
while (stones.length > 1) {
const x = stones.pop();
const y = stones.pop();
if (x === y) continue;
const d = Math.abs(x - y);
let idx = stones.length;
while (idx > 0) {
if (stones[idx - 1] <= d) break;
stones[idx] = stones[idx - 1];
--idx;
}
stones[idx] = d;
}
return stones.length === 1 ? stones[0] : 0;
};
```

### optimization

The above scheme first uses a global sort, and then uses a traversal based insertion behavior for the margin in the traversal. The optimization scheme here is very obvious. We can optimize the sorting method, so as to simplify the whole process.

Because the range of input data is`[1, 1000]`

Therefore, we can easily use bucket sorting to complete the initial sorting, and the subsequent residual processing will become easier. The specific codes are as follows:

```
const lastStoneWeight = stones => {
const buckets = new Uint8Array(1001);
let t = 0;
for (const val of stones) ++buckets[val];
for (let i = 1000; i > 0; --i) {
if (!buckets[i]) continue;
if (!t) { buckets[i] % 2 && (t = i); continue; }
const d = Math.abs(t - i);
t = d >= i ? d : (++buckets[d], 0);
--buckets[i++];
}
return t;
};
```

## summary

It is also an optimization based on bucket sorting, which is “really fragrant” in a specific scenario. I hope I can help my friends in need.

If you think it’s good, remember the “three companies”. Piggy loves you~

## Related links

- Activity title list
- Leetcode problem solving repo
- My segment fault column
- My Zhihu column