Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add solutions to lcci problem: No.03.01 #2531

Merged
merged 2 commits into from
Apr 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
188 changes: 143 additions & 45 deletions lcci/03.01.Three in One/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,28 +32,47 @@

## 解法

### 方法一
### 方法一:数组模拟

我们使用一个变量 $cap$ 来表示每个栈的大小,使用一个长度为 $3 \times \text{cap} + 3$ 的数组 $stk$ 来模拟三个栈,数组的前 $3 \times \text{cap}$ 个元素用来存储栈的元素,数组的后三个元素用来存储每个栈的元素个数。

对于 `push` 操作,我们首先判断栈是否已满,如果未满,则将元素压入栈中,并更新栈的元素个数。

对于 `pop` 操作,我们首先判断栈是否为空,如果不为空,则更新栈的元素个数,并返回栈顶元素。

对于 `peek` 操作,我们首先判断栈是否为空,如果不为空,则返回栈顶元素。

对于 `isEmpty` 操作,我们直接判断栈是否为空即可。对于栈 $i$,我们只需要判断 $stk[\text{cap} \times 3 + i]$ 是否为 $0$ 即可。

时间复杂度上,每个操作的时间复杂度均为 $O(1)$。空间复杂度为 $O(\text{cap})$,其中 $\text{cap}$ 为栈的大小。

<!-- tabs:start -->

```python
class TripleInOne:

def __init__(self, stackSize: int):
self._capacity = stackSize
self._s = [[], [], []]
self.cap = stackSize
self.stk = [0] * (self.cap * 3 + 3)

def push(self, stackNum: int, value: int) -> None:
if len(self._s[stackNum]) < self._capacity:
self._s[stackNum].append(value)
if self.stk[self.cap * 3 + stackNum] < self.cap:
self.stk[self.cap * stackNum + self.stk[self.cap * 3 + stackNum]] = value
self.stk[self.cap * 3 + stackNum] += 1

def pop(self, stackNum: int) -> int:
return -1 if self.isEmpty(stackNum) else self._s[stackNum].pop()
if self.isEmpty(stackNum):
return -1
self.stk[self.cap * 3 + stackNum] -= 1
return self.stk[self.cap * stackNum + self.stk[self.cap * 3 + stackNum]]

def peek(self, stackNum: int) -> int:
return -1 if self.isEmpty(stackNum) else self._s[stackNum][-1]
if self.isEmpty(stackNum):
return -1
return self.stk[self.cap * stackNum + self.stk[self.cap * 3 + stackNum] - 1]

def isEmpty(self, stackNum: int) -> bool:
return len(self._s[stackNum]) == 0
return self.stk[self.cap * 3 + stackNum] == 0


# Your TripleInOne object will be instantiated and called as such:
Expand All @@ -66,35 +85,35 @@ class TripleInOne:

```java
class TripleInOne {
private int[] s;
private int capacity;
private int cap;
private int[] stk;

public TripleInOne(int stackSize) {
s = new int[stackSize * 3 + 3];
capacity = stackSize;
cap = stackSize;
stk = new int[cap * 3 + 3];
}

public void push(int stackNum, int value) {
if (s[stackNum + 3 * capacity] < capacity) {
s[s[stackNum + 3 * capacity] * 3 + stackNum] = value;
++s[stackNum + 3 * capacity];
if (stk[cap * 3 + stackNum] < cap) {
stk[cap * stackNum + stk[cap * 3 + stackNum]] = value;
++stk[cap * 3 + stackNum];
}
}

public int pop(int stackNum) {
if (isEmpty(stackNum)) {
return -1;
}
--s[stackNum + 3 * capacity];
return s[s[stackNum + 3 * capacity] * 3 + stackNum];
--stk[cap * 3 + stackNum];
return stk[cap * stackNum + stk[cap * 3 + stackNum]];
}

public int peek(int stackNum) {
return isEmpty(stackNum) ? -1 : s[(s[stackNum + 3 * capacity] - 1) * 3 + stackNum];
return isEmpty(stackNum) ? -1 : stk[cap * stackNum + stk[cap * 3 + stackNum] - 1];
}

public boolean isEmpty(int stackNum) {
return s[stackNum + 3 * capacity] == 0;
return stk[cap * 3 + stackNum] == 0;
}
}

Expand All @@ -108,54 +127,86 @@ class TripleInOne {
*/
```

```cpp
class TripleInOne {
public:
TripleInOne(int stackSize) {
cap = stackSize;
stk.resize(cap * 3 + 3);
}

void push(int stackNum, int value) {
if (stk[cap * 3 + stackNum] < cap) {
stk[cap * stackNum + stk[cap * 3 + stackNum]] = value;
++stk[cap * 3 + stackNum];
}
}

int pop(int stackNum) {
if (isEmpty(stackNum)) {
return -1;
}
--stk[cap * 3 + stackNum];
return stk[cap * stackNum + stk[cap * 3 + stackNum]];
}

int peek(int stackNum) {
return isEmpty(stackNum) ? -1 : stk[cap * stackNum + stk[cap * 3 + stackNum] - 1];
}

bool isEmpty(int stackNum) {
return stk[cap * 3 + stackNum] == 0;
}

private:
int cap;
vector<int> stk;
};

/**
* Your TripleInOne object will be instantiated and called as such:
* TripleInOne* obj = new TripleInOne(stackSize);
* obj->push(stackNum,value);
* int param_2 = obj->pop(stackNum);
* int param_3 = obj->peek(stackNum);
* bool param_4 = obj->isEmpty(stackNum);
*/
```

```go
type TripleInOne struct {
data []int
offset [3]int
stackSize int
cap int
stk []int
}

func Constructor(stackSize int) TripleInOne {
total := stackSize * 3
data := make([]int, total)
offset := [3]int{}
for i := 0; i < 3; i++ {
offset[i] = i * stackSize
}
return TripleInOne{
data: data,
offset: offset,
stackSize: stackSize,
}
return TripleInOne{stackSize, make([]int, stackSize*3+3)}
}

func (this *TripleInOne) Push(stackNum int, value int) {
i := this.offset[stackNum]
if i < (stackNum+1)*this.stackSize {
this.data[i] = value
this.offset[stackNum]++
if this.stk[this.cap*3+stackNum] < this.cap {
this.stk[this.cap*stackNum+this.stk[this.cap*3+stackNum]] = value
this.stk[this.cap*3+stackNum]++
}
}

func (this *TripleInOne) Pop(stackNum int) int {
i := this.offset[stackNum]
if i == stackNum*this.stackSize {
if this.IsEmpty(stackNum) {
return -1
}
this.offset[stackNum]--
return this.data[i-1]
this.stk[this.cap*3+stackNum]--
return this.stk[this.cap*stackNum+this.stk[this.cap*3+stackNum]]
}

func (this *TripleInOne) Peek(stackNum int) int {
i := this.offset[stackNum]
if i == stackNum*this.stackSize {
if this.IsEmpty(stackNum) {
return -1
}
return this.data[i-1]
return this.stk[this.cap*stackNum+this.stk[this.cap*3+stackNum]-1]
}

func (this *TripleInOne) IsEmpty(stackNum int) bool {
return this.offset[stackNum] == stackNum*this.stackSize
return this.stk[this.cap*3+stackNum] == 0
}

/**
Expand All @@ -168,6 +219,53 @@ func (this *TripleInOne) IsEmpty(stackNum int) bool {
*/
```

```ts
class TripleInOne {
private cap: number;
private stk: number[];

constructor(stackSize: number) {
this.cap = stackSize;
this.stk = Array<number>(stackSize * 3 + 3).fill(0);
}

push(stackNum: number, value: number): void {
if (this.stk[this.cap * 3 + stackNum] < this.cap) {
this.stk[this.cap * stackNum + this.stk[this.cap * 3 + stackNum]] = value;
this.stk[this.cap * 3 + stackNum]++;
}
}

pop(stackNum: number): number {
if (this.isEmpty(stackNum)) {
return -1;
}
this.stk[this.cap * 3 + stackNum]--;
return this.stk[this.cap * stackNum + this.stk[this.cap * 3 + stackNum]];
}

peek(stackNum: number): number {
if (this.isEmpty(stackNum)) {
return -1;
}
return this.stk[this.cap * stackNum + this.stk[this.cap * 3 + stackNum] - 1];
}

isEmpty(stackNum: number): boolean {
return this.stk[this.cap * 3 + stackNum] === 0;
}
}

/**
* Your TripleInOne object will be instantiated and called as such:
* var obj = new TripleInOne(stackSize)
* obj.push(stackNum,value)
* var param_2 = obj.pop(stackNum)
* var param_3 = obj.peek(stackNum)
* var param_4 = obj.isEmpty(stackNum)
*/
```

<!-- tabs:end -->

<!-- end -->
Loading
Loading