mirror of
https://github.com/prdlk/leetcode.git
synced 2026-08-02 17:31:40 +00:00
chore(Blind): add answer key and solutions for deduction problems
This commit is contained in:
@@ -0,0 +1,151 @@
|
||||
// ============================================================
|
||||
// ANSWER KEY — open only after narrating all 6 out loud.
|
||||
// Solutions match your repo style exactly:
|
||||
// ~/Developer/github.com/prdlk/leetcode/work/Default
|
||||
// (object freq maps, (freq[n] || 0) + 1, same shapes)
|
||||
// ============================================================
|
||||
|
||||
// problem1 = LC 1365 — How Many Numbers Are Smaller Than Current
|
||||
// (your file: Easy/Array/1365...js — this IS your solution)
|
||||
// RULE: "output[i] = count of elements strictly smaller than arr[i];
|
||||
// ties don't count as smaller (that's the [7,7,7,7] example)."
|
||||
function problem1(nums) {
|
||||
// Step 1: Begin by initializing a [Frequency Map]
|
||||
const freq = {};
|
||||
for (let n of nums) freq[n] = (freq[n] || 0) + 1;
|
||||
|
||||
// Step 2: Sort the numbers by ascending order
|
||||
const sorted = Object.keys(freq).sort((a, b) => a - b);
|
||||
|
||||
// Step 3: Init a count of numbers smaller than the active number
|
||||
let count = 0;
|
||||
|
||||
// Step 4: Init a map to track number of values smaller for each number
|
||||
const smaller = {};
|
||||
|
||||
// Step 5: Iterate over the sorted list
|
||||
for (let num of sorted) {
|
||||
// Set count for active number — BEFORE adding own frequency,
|
||||
// so duplicates only see values strictly below them
|
||||
smaller[num] = count;
|
||||
|
||||
// Update the count by frequency
|
||||
count += freq[num];
|
||||
}
|
||||
|
||||
// Step 6: Use original list and find number of smaller values than it
|
||||
return nums.map((n) => smaller[n]);
|
||||
}
|
||||
// Narration reminders:
|
||||
// - "record before adding" is WHY [7,7,7,7] => [0,0,0,0]
|
||||
// - Object.keys returns strings; (a, b) => a - b coerces numerically
|
||||
// - quick brute-force alternative if short on time:
|
||||
// nums.map((n) => nums.filter((m) => m < n).length)
|
||||
|
||||
// problem2 = LC 451 — Sort Characters By Frequency (+ alpha tiebreak)
|
||||
// (your file: Medium/Hash Table/451...js — same, tiebreak included)
|
||||
// RULE: "rebuild the string most-frequent chars first; equal counts
|
||||
// break alphabetically."
|
||||
// DISCRIMINATOR: "bookkeeper" — e:3, then k:2/o:2 tie -> k before o
|
||||
// = alphabetical, NOT input order (o appeared first in the input!).
|
||||
function problem2(s) {
|
||||
// count the frequency of each character
|
||||
const freq = {};
|
||||
for (let c of s) freq[c] = (freq[c] || 0) + 1;
|
||||
|
||||
// sort the characters by frequency, ties alphabetical
|
||||
return s
|
||||
.split("")
|
||||
.sort((a, b) => freq[b] - freq[a] || a.localeCompare(b))
|
||||
.join("");
|
||||
}
|
||||
// Note vs your repo file: identical. localeCompare orders lowercase
|
||||
// before uppercase ("bbaA"), which is what the drill examples use.
|
||||
// LC 451 proper accepts any tie order — the tiebreak is the
|
||||
// interview twist Jim's source described.
|
||||
|
||||
// problem3 = LC 1636 — Sort Array by Increasing Frequency
|
||||
// (your file: Easy/Array/1636...js — this IS your solution)
|
||||
// RULE: "sort by frequency ascending; ties by VALUE DESCENDING."
|
||||
// DISCRIMINATOR: [2,3,1,3,2] -> 2 and 3 both appear twice, 3 first.
|
||||
function problem3(nums) {
|
||||
const freq = {};
|
||||
for (let n of nums) freq[n] = (freq[n] || 0) + 1;
|
||||
return nums.sort((a, b) => freq[a] - freq[b] || b - a);
|
||||
}
|
||||
// The idiom to say out loud: "primary key OR tiebreak — when the
|
||||
// frequency difference is 0 (falsy), JS falls through to b - a."
|
||||
|
||||
// problem4 = LC 387 — First Unique Character
|
||||
// (your file: Easy/Hash Table/387...js — this IS your solution)
|
||||
// RULE: "index of the first character appearing exactly once; -1 if none."
|
||||
// SHAPE TELL: output is a NUMBER, not an array.
|
||||
function problem4(s) {
|
||||
const freq = {};
|
||||
for (let c of s) freq[c] = (freq[c] || 0) + 1;
|
||||
|
||||
for (let i = 0; i < s.length; i++) {
|
||||
if (freq[s[i]] === 1) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
// Say it: "two passes — I can't know a char is unique until I've
|
||||
// seen the whole string."
|
||||
|
||||
// problem5 = LC 242 — Valid Anagram
|
||||
// (not in your repo yet — written in your exact style)
|
||||
// RULE: "true iff both strings have the same characters with the
|
||||
// same counts."
|
||||
// DISCRIMINATOR: ("aacc", "ccac") -> same char SET {a,c}, different
|
||||
// counts -> false. Kills set-equality.
|
||||
function problem5(s, t) {
|
||||
if (s.length !== t.length) return false;
|
||||
|
||||
const freq = {};
|
||||
for (let c of s) freq[c] = (freq[c] || 0) + 1;
|
||||
|
||||
// walk t, spending counts down; a missing/exhausted char fails
|
||||
for (let c of t) {
|
||||
if (!freq[c]) return false;
|
||||
freq[c]--;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// The length guard up front is what lets count-down work without a
|
||||
// final "all zeros" pass.
|
||||
|
||||
// problem6 = LC 347 — Top K Frequent Elements
|
||||
// (your file: Medium/Array/347...js — this IS your solution)
|
||||
// RULE: "return the k values that appear most often, most frequent
|
||||
// first."
|
||||
// SHAPE TELL: second argument k controls output length.
|
||||
// EDGE: [3,0,1,0] k=1 => [0] — value 0 is falsy but valid.
|
||||
function problem6(nums, k) {
|
||||
const freq = {};
|
||||
for (let n of nums) freq[n] = (freq[n] || 0) + 1;
|
||||
|
||||
return Object.keys(freq)
|
||||
.map(Number) // Object.keys gave us strings — convert back
|
||||
.sort((a, b) => freq[b] - freq[a])
|
||||
.slice(0, k);
|
||||
}
|
||||
// The .map(Number) is the classic gotcha to mention: without it you
|
||||
// return ["1","2"] instead of [1,2].
|
||||
|
||||
// ============================================================
|
||||
// THE HAMMER (all six are this skeleton):
|
||||
// 1. BUILD -> const freq = {}; for (let x of input)
|
||||
// freq[x] = (freq[x] || 0) + 1;
|
||||
// 2. ORDER -> sort keys/elements by the criterion the pattern demands
|
||||
// 3. DERIVE -> compute what each key maps to (count / rank / index)
|
||||
// 4. EMIT -> map back to input order / rebuild string / slice k
|
||||
//
|
||||
// SELF-SCORE per problem:
|
||||
// Rule stated in one sentence, verified vs ALL examples: /1
|
||||
// Tiebreak/edge named BEFORE coding (the discriminator): /1
|
||||
// Working code, narrated while typing: /1
|
||||
// 15+/18 = ready. Misses tell you what to re-drill Tuesday
|
||||
// morning (max 2 reps, then stop — rest beats an 11th rep).
|
||||
// ============================================================
|
||||
@@ -0,0 +1,82 @@
|
||||
// ============================================================
|
||||
// BLIND DEDUCTION SET — Monday evening, ONE round, then stop.
|
||||
// The 6 core interview problems, disguised exactly as they'd
|
||||
// appear Tuesday: no statement, just input => output pairs.
|
||||
// Rules: deduce the rule, SAY it in one sentence out loud,
|
||||
// state the plan (freq map? sort? tiebreak?), then implement.
|
||||
// Do NOT open blind-deduction-answers.js until finished.
|
||||
// Target: rule stated < 3 min, implemented < 6 min each.
|
||||
// ============================================================
|
||||
|
||||
// ---- problem1 ----
|
||||
// problem1([8, 1, 2, 2, 3]) => [4, 0, 1, 1, 3]
|
||||
// problem1([6, 5, 4, 8]) => [2, 1, 0, 3]
|
||||
// problem1([7, 7, 7, 7]) => [0, 0, 0, 0]
|
||||
// problem1([3, 1, 2]) => [2, 0, 1]
|
||||
// problem1([5]) => [0]
|
||||
// problem1([4, 1, 4, 1]) => [2, 0, 2, 0]
|
||||
function problem1(arr) {
|
||||
// your code
|
||||
}
|
||||
|
||||
// ---- problem2 ----
|
||||
// problem2("tree") => "eert"
|
||||
// problem2("cccaaa") => "aaaccc"
|
||||
// problem2("Aabb") => "bbaA"
|
||||
// problem2("z") => "z"
|
||||
// problem2("bookkeeper") => "eeekkoobpr"
|
||||
// problem2("mississippi") => "iiiissssppm"
|
||||
function problem2(str) {
|
||||
// your code
|
||||
}
|
||||
|
||||
// ---- problem3 ----
|
||||
// problem3([1, 1, 2, 2, 2, 3]) => [3, 1, 1, 2, 2, 2]
|
||||
// problem3([2, 3, 1, 3, 2]) => [1, 3, 3, 2, 2]
|
||||
// problem3([-1, 1, -6, 4, 5, -6, 1, 4, 1]) => [5, -1, 4, 4, -6, -6, 1, 1, 1]
|
||||
// problem3([9]) => [9]
|
||||
// problem3([5, 5, 4, 4]) => [5, 5, 4, 4]
|
||||
function problem3(arr) {
|
||||
// your code
|
||||
}
|
||||
|
||||
// ---- problem4 ----
|
||||
// problem4("leetcode") => 0
|
||||
// problem4("loveleetcode") => 2
|
||||
// problem4("aabb") => -1
|
||||
// problem4("x") => 0
|
||||
// problem4("aabbc") => 4
|
||||
// problem4("aa") => -1
|
||||
function problem4(str) {
|
||||
// your code
|
||||
}
|
||||
|
||||
// ---- problem5 ----
|
||||
// problem5("anagram", "nagaram") => true
|
||||
// problem5("rat", "car") => false
|
||||
// problem5("a", "ab") => false
|
||||
// problem5("", "") => true
|
||||
// problem5("aacc", "ccac") => false
|
||||
// problem5("listen", "silent") => true
|
||||
function problem5(s, t) {
|
||||
// your code
|
||||
}
|
||||
|
||||
// ---- problem6 ----
|
||||
// problem6([1, 1, 1, 2, 2, 3], 2) => [1, 2]
|
||||
// problem6([1], 1) => [1]
|
||||
// problem6([4, 4, 4, 6, 6, 7, 7, 7, 7], 2) => [7, 4]
|
||||
// problem6([5, 5, 5, 5], 1) => [5]
|
||||
// problem6([3, 0, 1, 0], 1) => [0]
|
||||
// problem6([2, 2, 3, 3, 1], 3) => [2, 3, 1]
|
||||
function problem6(arr, k) {
|
||||
// your code
|
||||
}
|
||||
|
||||
// ---- harness: uncomment per problem after implementing ----
|
||||
// console.log(problem1([8, 1, 2, 2, 3]), problem1([4, 1, 4, 1]));
|
||||
// console.log(problem2("tree"), problem2("bookkeeper"));
|
||||
// console.log(problem3([2, 3, 1, 3, 2]), problem3([5, 5, 4, 4]));
|
||||
// console.log(problem4("loveleetcode"), problem4("aabbc"));
|
||||
// console.log(problem5("anagram", "nagaram"), problem5("aacc", "ccac"));
|
||||
// console.log(problem6([4, 4, 4, 6, 6, 7, 7, 7, 7], 2), problem6([2, 2, 3, 3, 1], 3));
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 1365. How Many Numbers Are Smaller Than the Current Number
|
||||
* Difficulty: Easy
|
||||
* https://leetcode.com/problems/how-many-numbers-are-smaller-than-the-current-number/
|
||||
*
|
||||
* ──────────────────────────────────────────────────
|
||||
*
|
||||
* Given the array nums, for each nums[i] find out how many numbers in
|
||||
* the array are smaller than it. That is, for each nums[i] you have to
|
||||
* count the number of valid j's such that j != i and nums[j] < nums[i].
|
||||
*
|
||||
* Return the answer in an array.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Example 1:
|
||||
*
|
||||
* Input: nums = [8,1,2,2,3]
|
||||
* Output: [4,0,1,1,3]
|
||||
* Explanation:
|
||||
* For nums[0]=8 there exist four smaller numbers than it (1, 2, 2 and
|
||||
* 3).
|
||||
* For nums[1]=1 does not exist any smaller number than it.
|
||||
* For nums[2]=2 there exist one smaller number than it (1).
|
||||
* For nums[3]=2 there exist one smaller number than it (1).
|
||||
* For nums[4]=3 there exist three smaller numbers than it (1, 2 and 2).
|
||||
*
|
||||
* Example 2:
|
||||
*
|
||||
* Input: nums = [6,5,4,8]
|
||||
* Output: [2,1,0,3]
|
||||
*
|
||||
* Example 3:
|
||||
*
|
||||
* Input: nums = [7,7,7,7]
|
||||
* Output: [0,0,0,0]
|
||||
*
|
||||
*
|
||||
*
|
||||
* Constraints:
|
||||
*
|
||||
* • 2 <= nums.length <= 500
|
||||
*
|
||||
* • 0 <= nums[i] <= 100
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {number[]} nums
|
||||
* @return {number[]}
|
||||
*/
|
||||
|
||||
var smallerNumbersThanCurrent = function (nums) {
|
||||
// Step 1: Begin by initializing a [Frequency Map]()
|
||||
const freq = {};
|
||||
for (let n of nums) freq[n] = (freq[n] || 0) + 1;
|
||||
|
||||
// Step 2: Sort the numbers by ascending order
|
||||
const sorted = Object.keys(freq).sort((a, b) => a - b);
|
||||
|
||||
// Step 3: Init a count of numbers smaller than the active number
|
||||
let count = 0;
|
||||
|
||||
// Step 4: Init a map to track number of values smaller for each number
|
||||
const smaller = {};
|
||||
|
||||
// Step 5: Iterate over the sorted list
|
||||
for (let num of sorted) {
|
||||
// Set count for active number
|
||||
smaller[num] = count;
|
||||
|
||||
// Update the count by frequency
|
||||
count += freq[num];
|
||||
}
|
||||
|
||||
// Step 6: Use original list and find number of smaller values than it
|
||||
return nums.map((n) => smaller[n]);
|
||||
};
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 1636. Sort Array by Increasing Frequency
|
||||
* Difficulty: Easy
|
||||
* https://leetcode.com/problems/sort-array-by-increasing-frequency/
|
||||
*
|
||||
* ──────────────────────────────────────────────────
|
||||
*
|
||||
* Given an array of integers nums, sort the array in increasing order
|
||||
* based on the frequency of the values. If multiple values have the same
|
||||
* frequency, sort them in decreasing order.
|
||||
*
|
||||
* Return the sorted array.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Example 1:
|
||||
*
|
||||
* Input: nums = [1,1,2,2,2,3]
|
||||
* Output: [3,1,1,2,2,2]
|
||||
* Explanation: '3' has a frequency of 1, '1' has a frequency of 2, and
|
||||
* '2' has a frequency of 3.
|
||||
*
|
||||
* Example 2:
|
||||
*
|
||||
* Input: nums = [2,3,1,3,2]
|
||||
* Output: [1,3,3,2,2]
|
||||
* Explanation: '2' and '3' both have a frequency of 2, so they are
|
||||
* sorted in decreasing order.
|
||||
*
|
||||
* Example 3:
|
||||
*
|
||||
* Input: nums = [-1,1,-6,4,5,-6,1,4,1]
|
||||
* Output: [5,-1,4,4,-6,-6,1,1,1]
|
||||
*
|
||||
*
|
||||
*
|
||||
* Constraints:
|
||||
*
|
||||
* • 1 <= nums.length <= 100
|
||||
*
|
||||
* • -100 <= nums[i] <= 100
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {number[]} nums
|
||||
* @return {number[]}
|
||||
*/
|
||||
var frequencySort = function (nums) {
|
||||
const freq = {};
|
||||
for (let n of nums) freq[n] = (freq[n] || 0) + 1;
|
||||
return nums.sort((a, b) => freq[a] - freq[b] || b - a);
|
||||
};
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 387. First Unique Character in a String
|
||||
* Difficulty: Easy
|
||||
* https://leetcode.com/problems/first-unique-character-in-a-string/
|
||||
*
|
||||
* ──────────────────────────────────────────────────
|
||||
*
|
||||
* Given a string s, find the first non-repeating character in it and
|
||||
* return its index. If it does not exist, return -1.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Example 1:
|
||||
*
|
||||
* Input: s = "leetcode"
|
||||
*
|
||||
* Output: 0
|
||||
*
|
||||
* Explanation:
|
||||
*
|
||||
* The character 'l' at index 0 is the first character that does not
|
||||
* occur at any other index.
|
||||
*
|
||||
* Example 2:
|
||||
*
|
||||
* Input: s = "loveleetcode"
|
||||
*
|
||||
* Output: 2
|
||||
*
|
||||
* Example 3:
|
||||
*
|
||||
* Input: s = "aabb"
|
||||
*
|
||||
* Output: -1
|
||||
*
|
||||
*
|
||||
*
|
||||
* Constraints:
|
||||
*
|
||||
* • 1 <= s.length <= 10^5
|
||||
*
|
||||
* • s consists of only lowercase English letters.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {string} s
|
||||
* @return {number}
|
||||
*/
|
||||
var firstUniqChar = function (s) {
|
||||
const freq = {};
|
||||
for (let c of s) freq[c] = (freq[c] || 0) + 1;
|
||||
|
||||
for (let i = 0; i < s.length; i++) {
|
||||
if (freq[s[i]] === 1) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 347. Top K Frequent Elements
|
||||
* Difficulty: Medium
|
||||
* https://leetcode.com/problems/top-k-frequent-elements/
|
||||
*
|
||||
* ──────────────────────────────────────────────────
|
||||
*
|
||||
* Given an integer array nums and an integer k, return the k most
|
||||
* frequent elements. You may return the answer in any order.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Example 1:
|
||||
*
|
||||
* Input: nums = [1,1,1,2,2,3], k = 2
|
||||
*
|
||||
* Output: [1,2]
|
||||
*
|
||||
* Example 2:
|
||||
*
|
||||
* Input: nums = [1], k = 1
|
||||
*
|
||||
* Output: [1]
|
||||
*
|
||||
* Example 3:
|
||||
*
|
||||
* Input: nums = [1,2,1,2,1,2,3,1,3,2], k = 2
|
||||
*
|
||||
* Output: [1,2]
|
||||
*
|
||||
*
|
||||
*
|
||||
* Constraints:
|
||||
*
|
||||
* • 1 <= nums.length <= 10^5
|
||||
*
|
||||
* • -10^4 <= nums[i] <= 10^4
|
||||
*
|
||||
* • k is in the range [1, the number of unique elements in the array].
|
||||
*
|
||||
* • It is guaranteed that the answer is unique.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Follow up: Your algorithm's time complexity must be better than O(n
|
||||
* log n), where n is the array's size.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {number[]} nums
|
||||
* @param {number} k
|
||||
* @return {number[]}
|
||||
*/
|
||||
var topKFrequent = function (nums, k) {
|
||||
const freq = {};
|
||||
for (let n of nums) freq[n] = (freq[n] || 0) + 1;
|
||||
|
||||
return Object.keys(freq)
|
||||
.map(Number)
|
||||
.sort((a, b) => freq[b] - freq[a])
|
||||
.slice(0, k);
|
||||
};
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 451. Sort Characters By Frequency
|
||||
* Difficulty: Medium
|
||||
* https://leetcode.com/problems/sort-characters-by-frequency/
|
||||
*
|
||||
* ──────────────────────────────────────────────────
|
||||
*
|
||||
* Given a string s, sort it in decreasing order based on the frequency
|
||||
* of the characters. The frequency of a character is the number of times
|
||||
* it appears in the string.
|
||||
*
|
||||
* Return the sorted string. If there are multiple answers, return any
|
||||
* of them.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Example 1:
|
||||
*
|
||||
* Input: s = "tree"
|
||||
* Output: "eert"
|
||||
* Explanation: 'e' appears twice while 'r' and 't' both appear once.
|
||||
* So 'e' must appear before both 'r' and 't'. Therefore "eetr" is also
|
||||
* a valid answer.
|
||||
*
|
||||
* Example 2:
|
||||
*
|
||||
* Input: s = "cccaaa"
|
||||
* Output: "aaaccc"
|
||||
* Explanation: Both 'c' and 'a' appear three times, so both "cccaaa"
|
||||
* and "aaaccc" are valid answers.
|
||||
* Note that "cacaca" is incorrect, as the same characters must be
|
||||
* together.
|
||||
*
|
||||
* Example 3:
|
||||
*
|
||||
* Input: s = "Aabb"
|
||||
* Output: "bbAa"
|
||||
* Explanation: "bbaA" is also a valid answer, but "Aabb" is incorrect.
|
||||
* Note that 'A' and 'a' are treated as two different characters.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Constraints:
|
||||
*
|
||||
* • 1 <= s.length <= 5 * 10^5
|
||||
*
|
||||
* • s consists of uppercase and lowercase English letters and digits.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {string} s
|
||||
* @return {string}
|
||||
*/
|
||||
var frequencySort = function (s) {
|
||||
// count the frequency of each character
|
||||
const freq = {};
|
||||
for (let c of s) freq[c] = (freq[c] || 0) + 1;
|
||||
|
||||
// sort the characters by frequency
|
||||
return s
|
||||
.split("")
|
||||
.sort((a, b) => freq[b] - freq[a] || a.localeCompare(b))
|
||||
.join("");
|
||||
};
|
||||
Reference in New Issue
Block a user