feat: add solution for smallest palindromic rearrangement ii
- add problem 3518 implementation - add build configuration with debug and release modes - add test cases and examples - add makefile for problem-specific build workflow
This commit is contained in:
@@ -0,0 +1,46 @@
|
|||||||
|
TARGET_NAME := smallest_palindromic_rearrangement_ii
|
||||||
|
|
||||||
|
PROBLEM_ID := $(notdir $(CURDIR))
|
||||||
|
|
||||||
|
BUILD_DIR := $(BUILD_ROOT)/$(PROBLEM_ID)
|
||||||
|
|
||||||
|
TARGET := $(BUILD_DIR)/$(TARGET_NAME)
|
||||||
|
|
||||||
|
SOURCES := \
|
||||||
|
main.cpp \
|
||||||
|
solution.cpp
|
||||||
|
|
||||||
|
OBJECTS := $(SOURCES:%.cpp=$(BUILD_DIR)/%.o)
|
||||||
|
|
||||||
|
|
||||||
|
all: build
|
||||||
|
|
||||||
|
|
||||||
|
build: $(TARGET)
|
||||||
|
|
||||||
|
|
||||||
|
$(TARGET): $(OBJECTS)
|
||||||
|
@mkdir -p $(BUILD_DIR)
|
||||||
|
$(CC) $(CFLAGS) $^ $(LDFLAGS) -o $@
|
||||||
|
|
||||||
|
|
||||||
|
$(BUILD_DIR)/%.o: %.cpp
|
||||||
|
@mkdir -p $(BUILD_DIR)
|
||||||
|
$(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
|
||||||
|
run: build
|
||||||
|
$(TARGET)
|
||||||
|
|
||||||
|
|
||||||
|
test: run
|
||||||
|
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(BUILD_DIR)
|
||||||
|
|
||||||
|
|
||||||
|
rebuild: clean build
|
||||||
|
|
||||||
|
|
||||||
|
.PHONY: all build run test clean rebuild
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
# 3518. Smallest Palindromic Rearrangement II
|
||||||
|
|
||||||
|
You are given a string `s` and an integer `k`.
|
||||||
|
|
||||||
|
Return the k-th palindromic of `s`. If there are fewer than `k` distinct palindromic permutations, return an empty string.
|
||||||
|
|
||||||
|
Note: Different rearrangements that yield the same palindromic string are considered identical and are counted once.
|
||||||
|
|
||||||
|
## Example 1
|
||||||
|
|
||||||
|
**Input:**
|
||||||
|
|
||||||
|
```text
|
||||||
|
s = "abba", k = 2
|
||||||
|
````
|
||||||
|
|
||||||
|
**Output:**
|
||||||
|
|
||||||
|
```text
|
||||||
|
"baab"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Explanation:**
|
||||||
|
|
||||||
|
The two distinct palindromic rearrangements of `"abba"` are `"abba"` and `"baab"`.
|
||||||
|
|
||||||
|
Lexicographically, `"abba"` comes before `"baab"`. Since `k = 2`, the output is `"baab"`.
|
||||||
|
|
||||||
|
## Example 2
|
||||||
|
|
||||||
|
**Input:**
|
||||||
|
|
||||||
|
```text
|
||||||
|
s = "aa", k = 2
|
||||||
|
```
|
||||||
|
|
||||||
|
**Output:**
|
||||||
|
|
||||||
|
```text
|
||||||
|
""
|
||||||
|
```
|
||||||
|
|
||||||
|
**Explanation:**
|
||||||
|
|
||||||
|
There is only one palindromic rearrangement: `"aa"`.
|
||||||
|
|
||||||
|
The output is an empty string since `k = 2` exceeds the number of possible rearrangements.
|
||||||
|
|
||||||
|
## Example 3
|
||||||
|
|
||||||
|
**Input:**
|
||||||
|
|
||||||
|
```text
|
||||||
|
s = "bacab", k = 1
|
||||||
|
```
|
||||||
|
|
||||||
|
**Output:**
|
||||||
|
|
||||||
|
```text
|
||||||
|
"abcba"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Explanation:**
|
||||||
|
|
||||||
|
The two distinct palindromic rearrangements of `"bacab"` are `"abcba"` and `"bacab"`.
|
||||||
|
|
||||||
|
Lexicographically, `"abcba"` comes before `"bacab"`. Since `k = 1`, the output is `"abcba"`.
|
||||||
|
|
||||||
|
## Constraints
|
||||||
|
|
||||||
|
* `1 <= s.length <= 104`
|
||||||
|
* `s` consists of lowercase English letters.
|
||||||
|
* `s` is guaranteed to be palindromic.
|
||||||
|
* `1 <= k <= 106`
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
#include "solution.cpp"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
(void)argc;
|
||||||
|
(void)argv;
|
||||||
|
|
||||||
|
Solution s;
|
||||||
|
|
||||||
|
// Example 1
|
||||||
|
{
|
||||||
|
std::string result = s.smallestPalindrome("abba", 2);
|
||||||
|
assert(result == "baab");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Example 2
|
||||||
|
{
|
||||||
|
std::string result = s.smallestPalindrome("aa", 2);
|
||||||
|
assert(result == "");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Example 3
|
||||||
|
{
|
||||||
|
std::string result = s.smallestPalindrome("bacab", 1);
|
||||||
|
assert(result == "abcba");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Additional tests
|
||||||
|
|
||||||
|
// Single palindrome
|
||||||
|
{
|
||||||
|
std::string result = s.smallestPalindrome("aaa", 1);
|
||||||
|
assert(result == "aaa");
|
||||||
|
}
|
||||||
|
|
||||||
|
// k exceeds number of permutations
|
||||||
|
{
|
||||||
|
std::string result = s.smallestPalindrome("aabb", 3);
|
||||||
|
assert(result == "");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Two different characters
|
||||||
|
{
|
||||||
|
std::string result = s.smallestPalindrome("aabbcc", 1);
|
||||||
|
assert(result == "abccba");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Already sorted palindrome
|
||||||
|
{
|
||||||
|
std::string result = s.smallestPalindrome("abcba", 2);
|
||||||
|
assert(result == "bacab");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "All tests passed!\n";
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
#include <algorithm>
|
||||||
|
#include <limits>
|
||||||
|
#include <set>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
using std::set;
|
||||||
|
using std::string;
|
||||||
|
using std::ranges::next_permutation;
|
||||||
|
using std::ranges::reverse;
|
||||||
|
using std::ranges::sort;
|
||||||
|
|
||||||
|
class Solution {
|
||||||
|
public:
|
||||||
|
string smallestPalindrome(string s, int k) {
|
||||||
|
|
||||||
|
string half = s.substr(0, s.size() / 2);
|
||||||
|
|
||||||
|
sort(half);
|
||||||
|
|
||||||
|
set<string> permutations;
|
||||||
|
|
||||||
|
do {
|
||||||
|
permutations.insert(half);
|
||||||
|
} while (next_permutation(half).found);
|
||||||
|
|
||||||
|
if (permutations.size() > std::numeric_limits<int>::max()) {
|
||||||
|
throw std::overflow_error("Number of permutations exceeds int limit");
|
||||||
|
}
|
||||||
|
int size = static_cast<int>(permutations.size());
|
||||||
|
|
||||||
|
if (k > size) {
|
||||||
|
return string();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto it = permutations.begin();
|
||||||
|
advance(it, k);
|
||||||
|
|
||||||
|
string mirroredHalf = *it;
|
||||||
|
reverse(mirroredHalf);
|
||||||
|
|
||||||
|
return *it + mirroredHalf;
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
export ROOT_DIR := $(CURDIR)
|
||||||
|
|
||||||
|
export BUILD_ROOT := $(ROOT_DIR)/build
|
||||||
|
|
||||||
|
export CC = gcc
|
||||||
|
export LDFLAGS = -lstdc++
|
||||||
|
|
||||||
|
BUILD_TYPE ?= Release
|
||||||
|
|
||||||
|
ifeq ($(BUILD_TYPE),Debug)
|
||||||
|
export CFLAGS = -std=c++23 -Wall -Wextra -Werror -Wpedantic -g -O0
|
||||||
|
else ifeq ($(BUILD_TYPE),Release)
|
||||||
|
export CFLAGS = -std=c++23 -Wall -Wextra -Werror -Wpedantic -O2
|
||||||
|
else
|
||||||
|
$(error Unknown BUILD_TYPE: $(BUILD_TYPE))
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
.PHONY: all clean build run test rebuild
|
||||||
|
|
||||||
|
all:
|
||||||
|
ifndef PROBLEM_ID
|
||||||
|
$(error PROBLEM_ID is not set)
|
||||||
|
endif
|
||||||
|
$(MAKE) -C $(PROBLEM_ID)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(BUILD_ROOT)
|
||||||
|
|
||||||
|
# NOTE: Examples
|
||||||
|
# make build PROBLEM_ID=3518 BUILD_TYPE=Debug
|
||||||
|
# make build PROBLEM_ID=3518
|
||||||
|
build:
|
||||||
|
mkdir -p $(BUILD_ROOT)/$(PROBLEM_ID)
|
||||||
|
$(MAKE) -C $(PROBLEM_ID) build
|
||||||
|
|
||||||
|
run:
|
||||||
|
$(MAKE) -C $(PROBLEM_ID) run
|
||||||
|
|
||||||
|
test:
|
||||||
|
$(MAKE) -C $(PROBLEM_ID) test
|
||||||
|
|
||||||
|
rebuild:
|
||||||
|
$(MAKE) -C $(PROBLEM_ID) clean
|
||||||
|
$(MAKE) -C $(PROBLEM_ID) build
|
||||||
Reference in New Issue
Block a user