adding the map animation
This commit is contained in:
committed by
JamesFlare1212
parent
c3588e8541
commit
50bbf8c2a7
72
animations/maps/example1.html
Normal file
72
animations/maps/example1.html
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Contains Nearby Duplicate Visualization</title>
|
||||||
|
<link rel="stylesheet" href="style.css">
|
||||||
|
<!-- Load Konva.js -->
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/konva@8.3.13/konva.min.js"></script>
|
||||||
|
<script src="script.js" defer></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Contains Nearby Duplicate Using std::map</h1>
|
||||||
|
<p>This visualization demonstrates the algorithm that checks if an array contains duplicates within distance k.</p>
|
||||||
|
|
||||||
|
<div class="visualization-container">
|
||||||
|
<div class="left-panel">
|
||||||
|
<div class="code-container">
|
||||||
|
<pre><code id="codeDisplay"></code></pre>
|
||||||
|
</div>
|
||||||
|
<div class="explanation-result-container">
|
||||||
|
<div class="explanation" id="explanation">
|
||||||
|
Select a test case and click "Next Step" to begin the animation.
|
||||||
|
</div>
|
||||||
|
<div class="result-container" id="resultContainer">
|
||||||
|
Result: <span id="result"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="visualization-panel">
|
||||||
|
<div class="case-description" id="caseDescription"></div>
|
||||||
|
|
||||||
|
<div class="top-controls">
|
||||||
|
<div class="test-case-btns">
|
||||||
|
<button class="test-btn active" data-testcase="0">Test Case 1</button>
|
||||||
|
<button class="test-btn" data-testcase="1">Test Case 2</button>
|
||||||
|
<button class="test-btn" data-testcase="2">Test Case 3</button>
|
||||||
|
<button class="test-btn" data-testcase="3">Test Case 4</button>
|
||||||
|
<button class="test-btn" data-testcase="4">Test Case 5</button>
|
||||||
|
<button class="test-btn" data-testcase="5">Test Case 6</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="controls">
|
||||||
|
<button id="nextStep">Next Step</button>
|
||||||
|
<button id="resetBtn">Reset</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="visualization-area">
|
||||||
|
<div class="array-container" id="arrayContainer"></div>
|
||||||
|
<div class="map-container" id="mapContainer"></div>
|
||||||
|
|
||||||
|
<div class="color-key">
|
||||||
|
<div class="color-key-label">Color Key:</div>
|
||||||
|
<div class="key-item">
|
||||||
|
<div class="key-color key-current"></div>
|
||||||
|
<div class="key-description">Current Element</div>
|
||||||
|
</div>
|
||||||
|
<div class="key-item">
|
||||||
|
<div class="key-color key-found"></div>
|
||||||
|
<div class="key-description">Previous Occurrence</div>
|
||||||
|
</div>
|
||||||
|
<div class="key-item">
|
||||||
|
<div class="key-color key-duplicate"></div>
|
||||||
|
<div class="key-description">Duplicate Within Distance k</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
322
animations/maps/script.js
Normal file
322
animations/maps/script.js
Normal file
@@ -0,0 +1,322 @@
|
|||||||
|
// Define code content with syntax highlighting
|
||||||
|
const codeContent = [
|
||||||
|
'<span class="line-number">0.</span> <span style="color:blue">bool</span> containsNearbyDuplicate(<span style="color:blue">std::vector</span><<span style="color:blue">int</span>>& nums, <span style="color:blue">int</span> k) {',
|
||||||
|
'<span class="line-number">1.</span> <span style="color:blue">int</span> size = nums.size();',
|
||||||
|
'<span class="line-number">2.</span> <span style="color:green">// create the map, map key is the value of the vector element, map value is the index</span>',
|
||||||
|
'<span class="line-number">3.</span> <span style="color:blue">std::map</span><<span style="color:blue">int</span>,<span style="color:blue">int</span>> map1;',
|
||||||
|
'<span class="line-number">4.</span> <span style="color:blue">for</span>(<span style="color:blue">int</span> i=0; i<size; i++) {',
|
||||||
|
'<span class="line-number">5.</span> <span style="color:green">// if already exists</span>',
|
||||||
|
'<span class="line-number">6.</span> <span style="color:blue">if</span>(map1.find(nums[i]) != map1.end()) {',
|
||||||
|
'<span class="line-number">7.</span> <span style="color:blue">if</span>(i - map1[nums[i]] <= k) {',
|
||||||
|
'<span class="line-number">8.</span> <span style="color:blue">return true</span>;',
|
||||||
|
'<span class="line-number">9.</span> }',
|
||||||
|
'<span class="line-number">10.</span> }',
|
||||||
|
'<span class="line-number">11.</span> map1[nums[i]] = i;',
|
||||||
|
'<span class="line-number">12.</span> }',
|
||||||
|
'<span class="line-number">13.</span> <span style="color:blue">return false</span>;',
|
||||||
|
'<span class="line-number">14.</span> }'
|
||||||
|
];
|
||||||
|
|
||||||
|
// Test cases
|
||||||
|
const testCases = [
|
||||||
|
{
|
||||||
|
array: [1, 2, 3, 1],
|
||||||
|
k: 3,
|
||||||
|
description: "Array [1, 2, 3, 1] with k=3: Expected true (nums[0] == nums[3], |0-3| <= 3)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
array: [1, 0, 1, 1],
|
||||||
|
k: 1,
|
||||||
|
description: "Array [1, 0, 1, 1] with k=1: Expected true (nums[2] == nums[3], |2-3| <= 1)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
array: [1, 2, 3, 4, 5],
|
||||||
|
k: 2,
|
||||||
|
description: "Array [1, 2, 3, 4, 5] with k=2: Expected false (no duplicates within distance k)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
array: [1, 2, 3, 4, 1],
|
||||||
|
k: 4,
|
||||||
|
description: "Array [1, 2, 3, 4, 1] with k=4: Expected true (nums[0] == nums[4], |0-4| == 4 <= 4)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
array: [99, 99],
|
||||||
|
k: 1,
|
||||||
|
description: "Array [99, 99] with k=1: Expected true (nums[0] == nums[1], |0-1| <= 1)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
array: [1, 2, 3, 4, 5, 6],
|
||||||
|
k: 2,
|
||||||
|
description: "Array [1, 2, 3, 4, 5, 6] with k=2: Expected false (no duplicates)"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
// Global variables to track animation state
|
||||||
|
let currentTestCase = 0;
|
||||||
|
let currentStep = 0;
|
||||||
|
let map = new Map();
|
||||||
|
let result = false;
|
||||||
|
let animationFinished = false;
|
||||||
|
let currentLineHighlighted = -1;
|
||||||
|
|
||||||
|
// Initialize code display
|
||||||
|
function initCodeDisplay() {
|
||||||
|
const codeDisplay = document.getElementById('codeDisplay');
|
||||||
|
codeContent.forEach((line, index) => {
|
||||||
|
const lineDiv = document.createElement('div');
|
||||||
|
lineDiv.className = 'code-line';
|
||||||
|
lineDiv.setAttribute('data-line', index);
|
||||||
|
lineDiv.innerHTML = line;
|
||||||
|
codeDisplay.appendChild(lineDiv);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Highlight specific line of code
|
||||||
|
function highlightLine(lineNum) {
|
||||||
|
// Remove current highlight
|
||||||
|
if (currentLineHighlighted >= 0) {
|
||||||
|
const currentLine = document.querySelector(`.code-line[data-line="${currentLineHighlighted}"]`);
|
||||||
|
if (currentLine) {
|
||||||
|
currentLine.classList.remove('highlighted');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add new highlight
|
||||||
|
currentLineHighlighted = lineNum;
|
||||||
|
if (lineNum >= 0) {
|
||||||
|
const targetLine = document.querySelector(`.code-line[data-line="${lineNum}"]`);
|
||||||
|
if (targetLine) {
|
||||||
|
targetLine.classList.add('highlighted');
|
||||||
|
targetLine.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update test case description
|
||||||
|
function updateCaseDescription() {
|
||||||
|
const descEl = document.getElementById('caseDescription');
|
||||||
|
descEl.textContent = testCases[currentTestCase].description;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create array visualization
|
||||||
|
function createArrayVisualization() {
|
||||||
|
const container = document.getElementById('arrayContainer');
|
||||||
|
container.innerHTML = ''; // Clear container
|
||||||
|
|
||||||
|
const array = testCases[currentTestCase].array;
|
||||||
|
array.forEach((value, index) => {
|
||||||
|
const item = document.createElement('div');
|
||||||
|
item.className = 'array-item';
|
||||||
|
item.setAttribute('data-index', index);
|
||||||
|
item.textContent = value;
|
||||||
|
container.appendChild(item);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update map visualization
|
||||||
|
function updateMapVisualization() {
|
||||||
|
const container = document.getElementById('mapContainer');
|
||||||
|
container.innerHTML = ''; // Clear container
|
||||||
|
|
||||||
|
// Display current map entries
|
||||||
|
map.forEach((value, key) => {
|
||||||
|
const item = document.createElement('div');
|
||||||
|
item.className = 'map-item';
|
||||||
|
|
||||||
|
const keyDiv = document.createElement('div');
|
||||||
|
keyDiv.className = 'map-key';
|
||||||
|
keyDiv.textContent = `Key: ${key}`;
|
||||||
|
|
||||||
|
const valueDiv = document.createElement('div');
|
||||||
|
valueDiv.className = 'map-value';
|
||||||
|
valueDiv.textContent = `Index: ${value}`;
|
||||||
|
|
||||||
|
item.appendChild(keyDiv);
|
||||||
|
item.appendChild(valueDiv);
|
||||||
|
container.appendChild(item);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update explanation text
|
||||||
|
function updateExplanation(text) {
|
||||||
|
document.getElementById('explanation').textContent = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update result display
|
||||||
|
function updateResult(res, final = false) {
|
||||||
|
const resultEl = document.getElementById('result');
|
||||||
|
resultEl.textContent = res ? "true" : "false";
|
||||||
|
|
||||||
|
if (final) {
|
||||||
|
resultEl.className = res ? "success" : "failure";
|
||||||
|
} else {
|
||||||
|
resultEl.className = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Highlight array item
|
||||||
|
function highlightArrayItem(index, className) {
|
||||||
|
const items = document.querySelectorAll('.array-item');
|
||||||
|
if (index >= 0 && index < items.length) {
|
||||||
|
// Remove previous highlighting of the same class
|
||||||
|
items.forEach(item => {
|
||||||
|
if (item.classList.contains(className)) {
|
||||||
|
item.classList.remove(className);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add new highlight
|
||||||
|
items[index].classList.add(className);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove all highlights from array items
|
||||||
|
function clearArrayHighlights() {
|
||||||
|
const items = document.querySelectorAll('.array-item');
|
||||||
|
items.forEach(item => {
|
||||||
|
item.classList.remove('current', 'found', 'duplicate');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset animation state
|
||||||
|
function resetAnimation() {
|
||||||
|
currentStep = 0;
|
||||||
|
map = new Map();
|
||||||
|
result = false;
|
||||||
|
animationFinished = false;
|
||||||
|
|
||||||
|
highlightLine(-1);
|
||||||
|
clearArrayHighlights();
|
||||||
|
updateMapVisualization();
|
||||||
|
updateResult(false);
|
||||||
|
updateExplanation("Animation reset. Click 'Next Step' to begin.");
|
||||||
|
|
||||||
|
document.getElementById('nextStep').disabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle test case button clicks
|
||||||
|
function initTestCaseButtons() {
|
||||||
|
const buttons = document.querySelectorAll('.test-btn');
|
||||||
|
buttons.forEach(button => {
|
||||||
|
button.addEventListener('click', function() {
|
||||||
|
// Update active button
|
||||||
|
buttons.forEach(btn => btn.classList.remove('active'));
|
||||||
|
this.classList.add('active');
|
||||||
|
|
||||||
|
// Set current test case
|
||||||
|
currentTestCase = parseInt(this.getAttribute('data-testcase'));
|
||||||
|
|
||||||
|
// Reset and initialize visualization
|
||||||
|
resetAnimation();
|
||||||
|
updateCaseDescription();
|
||||||
|
createArrayVisualization();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Animation steps for containsNearbyDuplicate algorithm
|
||||||
|
async function runAnimationStep() {
|
||||||
|
const array = testCases[currentTestCase].array;
|
||||||
|
const k = testCases[currentTestCase].k;
|
||||||
|
|
||||||
|
if (animationFinished) {
|
||||||
|
updateExplanation("Animation complete. Choose another test case or click 'Reset' to run again.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (currentStep) {
|
||||||
|
case 0:
|
||||||
|
// Function definition
|
||||||
|
highlightLine(0);
|
||||||
|
updateExplanation(`Starting containsNearbyDuplicate function with array [${array.join(', ')}] and k=${k}`);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
// Get array size
|
||||||
|
highlightLine(1);
|
||||||
|
updateExplanation(`Getting array size: size = ${array.length}`);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
// Create map
|
||||||
|
highlightLine(3);
|
||||||
|
updateExplanation("Creating an empty map to store values and their indices");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// Handle main loop iterations
|
||||||
|
const loopIndex = Math.floor((currentStep - 3) / 3);
|
||||||
|
const stepInLoop = (currentStep - 3) % 3;
|
||||||
|
|
||||||
|
if (loopIndex >= array.length) {
|
||||||
|
// Loop finished, return result
|
||||||
|
highlightLine(13);
|
||||||
|
updateExplanation("No duplicates found within distance k. Returning false.");
|
||||||
|
updateResult(false, true);
|
||||||
|
animationFinished = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentValue = array[loopIndex];
|
||||||
|
|
||||||
|
if (stepInLoop === 0) {
|
||||||
|
// Start of loop iteration
|
||||||
|
highlightLine(4);
|
||||||
|
updateExplanation(`Starting iteration ${loopIndex}: Processing element nums[${loopIndex}] = ${currentValue}`);
|
||||||
|
clearArrayHighlights();
|
||||||
|
highlightArrayItem(loopIndex, 'current');
|
||||||
|
}
|
||||||
|
else if (stepInLoop === 1) {
|
||||||
|
// Check if value exists in map
|
||||||
|
highlightLine(6);
|
||||||
|
const exists = map.has(currentValue);
|
||||||
|
updateExplanation(`Checking if ${currentValue} already exists in the map: ${exists ? 'Found' : 'Not found'}`);
|
||||||
|
|
||||||
|
if (exists) {
|
||||||
|
const prevIndex = map.get(currentValue);
|
||||||
|
highlightArrayItem(prevIndex, 'found');
|
||||||
|
|
||||||
|
// Check if within k distance
|
||||||
|
highlightLine(7);
|
||||||
|
const diff = loopIndex - prevIndex;
|
||||||
|
const withinK = diff <= k;
|
||||||
|
|
||||||
|
if (withinK) {
|
||||||
|
// Found duplicate within k distance
|
||||||
|
highlightLine(8);
|
||||||
|
updateExplanation(`Found duplicate! nums[${prevIndex}] = nums[${loopIndex}] = ${currentValue}, and |${loopIndex} - ${prevIndex}| = ${diff} <= ${k}. Returning true.`);
|
||||||
|
updateResult(true, true);
|
||||||
|
highlightArrayItem(loopIndex, 'duplicate');
|
||||||
|
animationFinished = true;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
updateExplanation(`nums[${prevIndex}] = nums[${loopIndex}] = ${currentValue}, but |${loopIndex} - ${prevIndex}| = ${diff} > ${k}. Continue checking.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (stepInLoop === 2) {
|
||||||
|
// Update map
|
||||||
|
highlightLine(11);
|
||||||
|
map.set(currentValue, loopIndex);
|
||||||
|
updateMapVisualization();
|
||||||
|
updateExplanation(`Updating map: map[${currentValue}] = ${loopIndex}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
currentStep++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize on page load
|
||||||
|
window.onload = function() {
|
||||||
|
initCodeDisplay();
|
||||||
|
initTestCaseButtons();
|
||||||
|
updateCaseDescription();
|
||||||
|
createArrayVisualization();
|
||||||
|
|
||||||
|
// Set up event listeners
|
||||||
|
document.getElementById('nextStep').addEventListener('click', runAnimationStep);
|
||||||
|
document.getElementById('resetBtn').addEventListener('click', function() {
|
||||||
|
resetAnimation();
|
||||||
|
createArrayVisualization();
|
||||||
|
});
|
||||||
|
};
|
||||||
365
animations/maps/style.css
Normal file
365
animations/maps/style.css
Normal file
@@ -0,0 +1,365 @@
|
|||||||
|
html, body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
font-size: 16px;
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 12px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
font-size: 26px;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
text-align: center;
|
||||||
|
margin: 8px 0 12px;
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.visualization-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
max-width: 1800px;
|
||||||
|
margin: 0 auto;
|
||||||
|
height: 80vh;
|
||||||
|
gap: 20px;
|
||||||
|
padding: 0 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-panel {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 48%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.code-container {
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 15px;
|
||||||
|
flex-grow: 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
max-height: 52vh;
|
||||||
|
font-size: 16px;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.explanation-result-container {
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 15px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-key {
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
border-radius: 5px;
|
||||||
|
padding: 10px;
|
||||||
|
margin-top: 10px;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: space-around;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.key-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin: 4px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.key-color {
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
border-radius: 3px;
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.key-current {
|
||||||
|
background-color: #fffde7;
|
||||||
|
border: 2px solid #ffeb3b;
|
||||||
|
}
|
||||||
|
|
||||||
|
.key-found {
|
||||||
|
background-color: #e8f5e9;
|
||||||
|
border: 2px solid #4caf50;
|
||||||
|
}
|
||||||
|
|
||||||
|
.key-duplicate {
|
||||||
|
background-color: #ffebee;
|
||||||
|
border: 2px solid #f44336;
|
||||||
|
}
|
||||||
|
|
||||||
|
.key-description {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
margin: 0;
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
font-family: Consolas, "Courier New", monospace;
|
||||||
|
white-space: pre;
|
||||||
|
display: inline-block;
|
||||||
|
min-width: 700px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#codeDisplay {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-number {
|
||||||
|
color: #666;
|
||||||
|
display: inline-block;
|
||||||
|
min-width: 35px;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.code-line {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
position: relative;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 2px 0;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.code-line.highlighted {
|
||||||
|
background-color: #ffeb3b;
|
||||||
|
width: 100%;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.visualization-panel {
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 15px;
|
||||||
|
width: 48%;
|
||||||
|
height: 75vh;
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-controls {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.test-case-btns {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 6px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.test-btn {
|
||||||
|
padding: 6px 8px;
|
||||||
|
font-size: 14px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
background-color: #e0e0e0;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.test-btn:hover {
|
||||||
|
background-color: #d0d0d0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.test-btn.active {
|
||||||
|
background-color: #2196f3;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.case-description {
|
||||||
|
background-color: #e8e8e8;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 5px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
font-size: 15px;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.controls {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 15px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#nextStep, #resetBtn {
|
||||||
|
padding: 8px 15px;
|
||||||
|
font-size: 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: #4CAF50;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#resetBtn {
|
||||||
|
background-color: #f44336;
|
||||||
|
}
|
||||||
|
|
||||||
|
#nextStep:hover {
|
||||||
|
background-color: #45a049;
|
||||||
|
}
|
||||||
|
|
||||||
|
#resetBtn:hover {
|
||||||
|
background-color: #d32f2f;
|
||||||
|
}
|
||||||
|
|
||||||
|
#nextStep:disabled, #resetBtn:disabled {
|
||||||
|
background-color: #cccccc;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.visualization-area {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 15px;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 15px;
|
||||||
|
background-color: white;
|
||||||
|
border-radius: 5px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
max-height: 55vh;
|
||||||
|
flex-grow: 1;
|
||||||
|
padding-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.array-container, .map-container {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 15px 10px 28px 10px;
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
border-radius: 5px;
|
||||||
|
min-height: 80px;
|
||||||
|
position: relative;
|
||||||
|
margin-top: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.array-container::before, .map-container::before {
|
||||||
|
content: "Array";
|
||||||
|
position: absolute;
|
||||||
|
top: -20px;
|
||||||
|
left: 10px;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.map-container::before {
|
||||||
|
content: "Map";
|
||||||
|
}
|
||||||
|
|
||||||
|
.array-item, .map-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 55px;
|
||||||
|
height: 55px;
|
||||||
|
background-color: white;
|
||||||
|
border: 2px solid #ddd;
|
||||||
|
border-radius: 5px;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 16px;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.array-item {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.array-item::after {
|
||||||
|
content: attr(data-index);
|
||||||
|
position: absolute;
|
||||||
|
bottom: -20px;
|
||||||
|
font-size: 13px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.map-item {
|
||||||
|
width: 90px;
|
||||||
|
height: 70px;
|
||||||
|
margin: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.map-key {
|
||||||
|
font-size: 15px;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.map-value {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.current {
|
||||||
|
border-color: #ffeb3b;
|
||||||
|
background-color: #fffde7;
|
||||||
|
box-shadow: 0 0 5px #ffeb3b;
|
||||||
|
}
|
||||||
|
|
||||||
|
.found {
|
||||||
|
border-color: #4caf50;
|
||||||
|
background-color: #e8f5e9;
|
||||||
|
box-shadow: 0 0 5px #4caf50;
|
||||||
|
}
|
||||||
|
|
||||||
|
.duplicate {
|
||||||
|
border-color: #f44336;
|
||||||
|
background-color: #ffebee;
|
||||||
|
box-shadow: 0 0 5px #f44336;
|
||||||
|
}
|
||||||
|
|
||||||
|
.explanation {
|
||||||
|
font-size: 15px;
|
||||||
|
padding: 12px;
|
||||||
|
background-color: #e8e8e8;
|
||||||
|
border-radius: 5px;
|
||||||
|
min-height: 60px;
|
||||||
|
line-height: 1.4;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
overflow-y: auto;
|
||||||
|
max-height: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.result-container {
|
||||||
|
padding: 12px;
|
||||||
|
background-color: #e8e8e8;
|
||||||
|
border-radius: 5px;
|
||||||
|
text-align: center;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#result {
|
||||||
|
color: #2196f3;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.success {
|
||||||
|
color: #4caf50 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.failure {
|
||||||
|
color: #f44336 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-key-label {
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
@@ -233,6 +233,8 @@ Test Case 6: false
|
|||||||
You can also find this problem on Leetcode.
|
You can also find this problem on Leetcode.
|
||||||
- [Leetcode problem 219: Contains Duplicate II](https://leetcode.com/problems/contains-duplicate-ii/description/). Solution: [p219_contains_duplicate_ii.cpp](../../leetcode/p219_contains_duplicate_ii.cpp).
|
- [Leetcode problem 219: Contains Duplicate II](https://leetcode.com/problems/contains-duplicate-ii/description/). Solution: [p219_contains_duplicate_ii.cpp](../../leetcode/p219_contains_duplicate_ii.cpp).
|
||||||
|
|
||||||
|
- Play this [animation](https://jidongxiao.github.io/CSCI1200-DataStructures/animations/maps/example1.html) to understand how this program works.
|
||||||
|
|
||||||
## 15.11 More Leetcode Exercises
|
## 15.11 More Leetcode Exercises
|
||||||
|
|
||||||
- [Leetcode problem 1: Two Sum](https://leetcode.com/problems/two-sum/). Solution: [p1_twosum.cpp](../../leetcode/p1_twosum.cpp).
|
- [Leetcode problem 1: Two Sum](https://leetcode.com/problems/two-sum/). Solution: [p1_twosum.cpp](../../leetcode/p1_twosum.cpp).
|
||||||
|
|||||||
Reference in New Issue
Block a user