Skip to content

Commit d7f8a0a

Browse files
committed
chore(solution): add solution for LeetCode problem No.2468
1 parent 961afdb commit d7f8a0a

File tree

2 files changed

+330
-0
lines changed

2 files changed

+330
-0
lines changed

.astro/types.d.ts

+159
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
declare module 'astro:content' {
2+
interface Render {
3+
'.md': Promise<{
4+
Content: import('astro').MarkdownInstance<{}>['Content'];
5+
headings: import('astro').MarkdownHeading[];
6+
remarkPluginFrontmatter: Record<string, any>;
7+
}>;
8+
}
9+
}
10+
11+
declare module 'astro:content' {
12+
export { z } from 'astro/zod';
13+
export type CollectionEntry<C extends keyof typeof entryMap> =
14+
(typeof entryMap)[C][keyof (typeof entryMap)[C]];
15+
16+
// TODO: Remove this when having this fallback is no longer relevant. 2.3? 3.0? - erika, 2023-04-04
17+
/**
18+
* @deprecated
19+
* `astro:content` no longer provide `image()`.
20+
*
21+
* Please use it through `schema`, like such:
22+
* ```ts
23+
* import { defineCollection, z } from "astro:content";
24+
*
25+
* defineCollection({
26+
* schema: ({ image }) =>
27+
* z.object({
28+
* image: image(),
29+
* }),
30+
* });
31+
* ```
32+
*/
33+
export const image: never;
34+
35+
// This needs to be in sync with ImageMetadata
36+
export type ImageFunction = () => import('astro/zod').ZodObject<{
37+
src: import('astro/zod').ZodString;
38+
width: import('astro/zod').ZodNumber;
39+
height: import('astro/zod').ZodNumber;
40+
format: import('astro/zod').ZodUnion<
41+
[
42+
import('astro/zod').ZodLiteral<'png'>,
43+
import('astro/zod').ZodLiteral<'jpg'>,
44+
import('astro/zod').ZodLiteral<'jpeg'>,
45+
import('astro/zod').ZodLiteral<'tiff'>,
46+
import('astro/zod').ZodLiteral<'webp'>,
47+
import('astro/zod').ZodLiteral<'gif'>,
48+
import('astro/zod').ZodLiteral<'svg'>
49+
]
50+
>;
51+
}>;
52+
53+
type BaseSchemaWithoutEffects =
54+
| import('astro/zod').AnyZodObject
55+
| import('astro/zod').ZodUnion<import('astro/zod').AnyZodObject[]>
56+
| import('astro/zod').ZodDiscriminatedUnion<string, import('astro/zod').AnyZodObject[]>
57+
| import('astro/zod').ZodIntersection<
58+
import('astro/zod').AnyZodObject,
59+
import('astro/zod').AnyZodObject
60+
>;
61+
62+
type BaseSchema =
63+
| BaseSchemaWithoutEffects
64+
| import('astro/zod').ZodEffects<BaseSchemaWithoutEffects>;
65+
66+
export type SchemaContext = { image: ImageFunction };
67+
68+
type BaseCollectionConfig<S extends BaseSchema> = {
69+
schema?: S | ((context: SchemaContext) => S);
70+
};
71+
export function defineCollection<S extends BaseSchema>(
72+
input: BaseCollectionConfig<S>
73+
): BaseCollectionConfig<S>;
74+
75+
type EntryMapKeys = keyof typeof entryMap;
76+
type AllValuesOf<T> = T extends any ? T[keyof T] : never;
77+
type ValidEntrySlug<C extends EntryMapKeys> = AllValuesOf<(typeof entryMap)[C]>['slug'];
78+
79+
export function getEntryBySlug<
80+
C extends keyof typeof entryMap,
81+
E extends ValidEntrySlug<C> | (string & {})
82+
>(
83+
collection: C,
84+
// Note that this has to accept a regular string too, for SSR
85+
entrySlug: E
86+
): E extends ValidEntrySlug<C>
87+
? Promise<CollectionEntry<C>>
88+
: Promise<CollectionEntry<C> | undefined>;
89+
export function getCollection<C extends keyof typeof entryMap, E extends CollectionEntry<C>>(
90+
collection: C,
91+
filter?: (entry: CollectionEntry<C>) => entry is E
92+
): Promise<E[]>;
93+
export function getCollection<C extends keyof typeof entryMap>(
94+
collection: C,
95+
filter?: (entry: CollectionEntry<C>) => unknown
96+
): Promise<CollectionEntry<C>[]>;
97+
98+
type ReturnTypeOrOriginal<T> = T extends (...args: any[]) => infer R ? R : T;
99+
type InferEntrySchema<C extends keyof typeof entryMap> = import('astro/zod').infer<
100+
ReturnTypeOrOriginal<Required<ContentConfig['collections'][C]>['schema']>
101+
>;
102+
103+
const entryMap: {
104+
"leetcode-solutions": {
105+
"0003-longest-substring-without-repeating-characters.md": {
106+
id: "0003-longest-substring-without-repeating-characters.md",
107+
slug: "0003-longest-substring-without-repeating-characters",
108+
body: string,
109+
collection: "leetcode-solutions",
110+
data: InferEntrySchema<"leetcode-solutions">
111+
} & { render(): Render[".md"] },
112+
"0008-string-to-integer-atoi.md": {
113+
id: "0008-string-to-integer-atoi.md",
114+
slug: "0008-string-to-integer-atoi",
115+
body: string,
116+
collection: "leetcode-solutions",
117+
data: InferEntrySchema<"leetcode-solutions">
118+
} & { render(): Render[".md"] },
119+
"0053-maximum-subarray.md": {
120+
id: "0053-maximum-subarray.md",
121+
slug: "0053-maximum-subarray",
122+
body: string,
123+
collection: "leetcode-solutions",
124+
data: InferEntrySchema<"leetcode-solutions">
125+
} & { render(): Render[".md"] },
126+
"0231-power-of-two.md": {
127+
id: "0231-power-of-two.md",
128+
slug: "0231-power-of-two",
129+
body: string,
130+
collection: "leetcode-solutions",
131+
data: InferEntrySchema<"leetcode-solutions">
132+
} & { render(): Render[".md"] },
133+
"0628-maximum-product-of-three-numbers.md": {
134+
id: "0628-maximum-product-of-three-numbers.md",
135+
slug: "0628-maximum-product-of-three-numbers",
136+
body: string,
137+
collection: "leetcode-solutions",
138+
data: InferEntrySchema<"leetcode-solutions">
139+
} & { render(): Render[".md"] },
140+
"2400-number-of-ways-to-reach-a-position-after-exactly-k-steps.md": {
141+
id: "2400-number-of-ways-to-reach-a-position-after-exactly-k-steps.md",
142+
slug: "2400-number-of-ways-to-reach-a-position-after-exactly-k-steps",
143+
body: string,
144+
collection: "leetcode-solutions",
145+
data: InferEntrySchema<"leetcode-solutions">
146+
} & { render(): Render[".md"] },
147+
"2464-split-message-based-on-limit.md": {
148+
id: "2464-split-message-based-on-limit.md",
149+
slug: "2468-split-message-based-on-limit",
150+
body: string,
151+
collection: "leetcode-solutions",
152+
data: InferEntrySchema<"leetcode-solutions">
153+
} & { render(): Render[".md"] },
154+
},
155+
156+
};
157+
158+
type ContentConfig = typeof import("../src/content/config");
159+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
---
2+
title: "2468. Split message based on limit"
3+
slug: "2468-split-message-based-on-limit"
4+
keywords:
5+
- "split"
6+
- "message"
7+
- "limit"
8+
author: "ansidev"
9+
pubDate: "2023-05-21T21:17:10+07:00"
10+
difficulty: "Hard"
11+
tags:
12+
- "String"
13+
- "Binary Search"
14+
---
15+
16+
## Problem
17+
18+
You are given a string, **message**, and a positive integer, **limit**.
19+
20+
You must split `message` into one or more parts based on `limit`. Each resulting part should have the suffix `"<a/b>"`,
21+
where `"b"` is to be replaced with the total number of parts and `"a"` is to be **replaced** with the index of the part,
22+
starting from `1` and going up to `b`. Additionally, the length of each resulting part (including its suffix) should be
23+
**equal** to `limit`, except for the last part whose length can be **at most** `limit`.
24+
25+
The resulting parts should be formed such that when their suffixes are removed and they are all concatenated in order,
26+
they should be equal to `message`. Also, the result should contain as few parts as possible.
27+
28+
Return _the parts_ `message` _would be split into as an array of strings_. If it is impossible to split `message` as
29+
required, return _an empty array_.
30+
31+
**Example 1:**
32+
33+
```
34+
Input: message = "this is really a very awesome message", limit = 9
35+
Output: ["thi<1/14>","s i<2/14>","s r<3/14>","eal<4/14>","ly <5/14>","a v<6/14>","ery<7/14>"," aw<8/14>","eso<9/14>","me<10/14>"," m<11/14>","es<12/14>","sa<13/14>","ge<14/14>"]
36+
Explanation:
37+
The first 9 parts take 3 characters each from the beginning of message.
38+
The next 5 parts take 2 characters each to finish splitting message.
39+
In this example, each part, including the last, has length 9.
40+
It can be shown it is not possible to split message into less than 14 parts.
41+
```
42+
43+
**Example 2:**
44+
45+
```
46+
Input: message = "short message", limit = 15
47+
Output: ["short mess<1/2>","age<2/2>"]
48+
Explanation:
49+
Under the given constraints, the string can be split into two parts:
50+
- The first part comprises of the first 10 characters, and has a length 15.
51+
- The next part comprises of the last 3 characters, and has a length 8.
52+
```
53+
54+
**Constraints:**
55+
56+
- <code>1 <= message.length <= 10<sup>4</sup></code>
57+
- `message` consists only of lowercase English letters and `' '`.
58+
- <code>1 <= limit <= 10<sup>4</sup></code>
59+
60+
## Analysis
61+
62+
Assumming it is possible to split `message` into an array M, M has n elements, then:
63+
64+
`M[a] = message[j:j+k]<a/b>` // example: "short<1/5>"
65+
66+
> `message[j:j+k]` is substring of `message` from index `j` to index `j+k-1`.
67+
68+
```
69+
len(M[a]) = len(message[j:j+k]) + len(<a/b>)
70+
= len(message[j:j+k]) + len(</>) + len(a) + len(b)
71+
= len(message[j:j+k]) + 3 + len(a) + len(b)
72+
```
73+
74+
- Because `message[j:j+k]` cannot be empty, `len(message[j:j+k]) >= 1`.
75+
- `len(b) >= len(a) >= 1`.
76+
77+
=> `len(M[a]) = len(message[j:j+k]) + 3 + len(a) + len(b) >= 1 + 3 + 1 + 1 = 5`.
78+
79+
From the requirements:
80+
81+
> The length of each resulting part (including its suffix) should be **equal** to `limit`, except for the last part
82+
> whose length can be **at most** `limit`.
83+
84+
We have
85+
86+
- `len(M[a]) <= limit`.
87+
88+
=> `limit >= 5`.
89+
90+
- The maximum length of each message part is `limit`, so
91+
92+
- Calling L is the total length of all elements of M, `L <= b * limit`.
93+
- If a message part length is greater than `limit`, it is impossible to split the message as required.
94+
95+
#### Approach
96+
97+
From the above analysis, the logic can be presented as below:
98+
99+
- If `limit < 5`, it is impossible to split message as required, then return the empty string array immediately.
100+
- Otherwise, iterate from 1 to len(message) and for each index `a`, we will check if it is possible to split `message`
101+
into `a` parts that satisfies the requirements.
102+
- If we find the number of total message parts, it is simple to build the output array.
103+
104+
#### Solutions
105+
106+
```go
107+
package problem
108+
109+
import (
110+
"strconv"
111+
"strings"
112+
)
113+
114+
func splitMessage(message string, limit int) []string {
115+
if limit < 5 {
116+
return []string{}
117+
}
118+
119+
mLen := len(message)
120+
b := 1
121+
aLen := sz(1)
122+
123+
for b*limit < b*(sz(b)+3)+aLen+mLen {
124+
if sz(b)*2+3 >= limit {
125+
return []string{}
126+
}
127+
b++
128+
aLen = aLen + sz(b)
129+
}
130+
131+
rs := make([]string, 0)
132+
i := 0
133+
for a := 1; a <= b; a++ {
134+
var sb strings.Builder
135+
j := limit - (3 + sz(a) + sz(b))
136+
sb.WriteString(message[i:min(i+j, mLen)])
137+
sb.WriteRune('<')
138+
sb.WriteString(strconv.Itoa(a))
139+
sb.WriteRune('/')
140+
sb.WriteString(strconv.Itoa(b))
141+
sb.WriteRune('>')
142+
rs = append(rs, sb.String())
143+
i = i + j
144+
}
145+
146+
return rs
147+
}
148+
149+
func sz(i int) int {
150+
return len(strconv.Itoa(i))
151+
}
152+
```
153+
154+
### Complexity
155+
156+
In the worst case, `message` will be split character by character (length is one), that means we have to iterate from
157+
the start to the end index of `message` to find out the total parts number
158+
159+
=> Time complexity = O(n).
160+
161+
After that, we have to iterate over the `message` again to build the output array_
162+
163+
=> Time complexity = O(n).
164+
165+
=> Total time complexity is 2 * O(n) ~ O(n).
166+
167+
Space complexity for `mLen`, `b`, `aLen`, `i` is `O(1)`.
168+
169+
Space complexity for `rs` is `O(n)`.
170+
171+
=> Total space complexity is 4 * O(1) + O(n) ~ O(n).

0 commit comments

Comments
 (0)