编码面试中解决问题的终极指南

编码面试中解决问题的终极指南

面试问题编码的常见策略

两个指针

两个指针技术经常被用来有效地解决数组相关的问题。它涉及使用两个指针,它们要么朝彼此移动,要么朝同一方向移动。

示例:在排序数组中查找总和为目标值的一对数字。

/** * finds a pair of numbers in a sorted array that sum up to a target value. * uses the two-pointer technique for efficient searching. *  * @param {number[]} arr - the sorted array of numbers to search through. * @param {number} target - the target sum to find. * @returns {number[]|null} - returns an array containing the pair if found, or null if not found. */function findpairwithsum(arr, target) {  // initialize two pointers: one at the start and one at the end of the array  let left = 0;  let right = arr.length - 1;  // continue searching while the left pointer is less than the right pointer  while (left < right) {    console.log(`checking pair: ${arr[left]} and ${arr[right]}`);    // calculate the sum of the current pair    const sum = arr[left] + arr[right];    if (sum === target) {      // if the sum equals the target, we've found our pair      console.log(`found pair: ${arr[left]} + ${arr[right]} = ${target}`);      return [arr[left], arr[right]];    } else if (sum < target) {      // if the sum is less than the target, we need a larger sum      // so, we move the left pointer to the right to increase the sum      console.log(`sum ${sum} is less than target ${target}, moving left pointer`);      left++;    } else {      // if the sum is greater than the target, we need a smaller sum      // so, we move the right pointer to the left to decrease the sum      console.log(`sum ${sum} is greater than target ${target}, moving right pointer`);      right--;    }  }  // if we've exhausted all possibilities without finding a pair, return null  console.log("no pair found");  return null;}// example usageconst sortedarray = [1, 3, 5, 7, 9, 11];const targetsum = 14;findpairwithsum(sortedarray, targetsum);

滑动窗口

滑动窗口技术对于解决涉及数组或字符串中连续序列的问题非常有用。

示例:查找大小为 k 的子数组的最大和。

/** * finds the maximum sum of a subarray of size k in the given array. * @param {number[]} arr - the input array of numbers. * @param {number} k - the size of the subarray. * @returns {number|null} the maximum sum of a subarray of size k, or null if the array length is less than k. */function maxsubarraysum(arr, k) {  // check if the array length is less than k  if (arr.length < k) {    console.log("array length is less than k");    return null;  }  let maxsum = 0;  let windowsum = 0;  // calculate sum of first window  for (let i = 0; i < k; i++) {    windowsum += arr[i];  }  maxsum = windowsum;  console.log(`initial window sum: ${windowsum}, window: [${arr.slice(0, k)}]`);  // slide the window and update the maximum sum  for (let i = k; i  maxsum) {      maxsum = windowsum;      console.log(`new max sum found: ${maxsum}, window: [${arr.slice(i - k + 1, i + 1)}]`);    }  }  console.log(`final max sum: ${maxsum}`);  return maxsum;}// example usageconst array = [1, 4, 2, 10, 23, 3, 1, 0, 20];const k = 4;maxsubarraysum(array, k);

哈希表

哈希表非常适合解决需要快速查找或计算出现次数的问题。

示例:查找字符串中的第一个不重复字符。

/** * finds the first non-repeating character in a given string. * @param {string} str - the input string to search. * @returns {string|null} the first non-repeating character, or null if not found. */function firstnonrepeatingchar(str) {  const charcount = new map();  // count occurrences of each character  for (let char of str) {    charcount.set(char, (charcount.get(char) || 0) + 1);    console.log(`character ${char} count: ${charcount.get(char)}`);  }  // find the first character with count 1  for (let char of str) {    if (charcount.get(char) === 1) {      console.log(`first non-repeating character found: ${char}`);      return char;    }  }  console.log("no non-repeating character found");  return null;}// example usageconst inputstring = "aabccdeff";firstnonrepeatingchar(inputstring);

这些策略展示了解决常见编码面试问题的有效方法。每个示例中的详细日志记录有助于理解算法的逐步过程,这在面试中解释您的思维过程至关重要。

这是一个代码块,演示如何使用映射来更好地理解其中一些操作:

// create a new mapconst fruitinventory = new map();// set key-value pairsfruitinventory.set('apple', 5);fruitinventory.set('banana', 3);fruitinventory.set('orange', 2);console.log('initial inventory:', fruitinventory);// get a value using a keyconsole.log('number of apples:', fruitinventory.get('apple'));// check if a key existsconsole.log('do we have pears?', fruitinventory.has('pear'));// update a valuefruitinventory.set('banana', fruitinventory.get('banana') + 2);console.log('updated banana count:', fruitinventory.get('banana'));// delete a key-value pairfruitinventory.delete('orange');console.log('inventory after removing oranges:', fruitinventory);// iterate over the mapconsole.log('current inventory:');fruitinventory.foreach((count, fruit) => {  console.log(`${fruit}: ${count}`);});// get the size of the mapconsole.log('number of fruit types:', fruitinventory.size);// clear the entire mapfruitinventory.clear();console.log('inventory after clearing:', fruitinventory);

此示例演示了各种 map 操作:

创建新地图使用 添加键值对使用 检索值使用 检查密钥是否存在更新值使用 删除键值对使用 迭代地图获取地图的大小清除整个地图 这些操作与firstnonrepeatingchar函数中使用的操作类似,我们使用map来统计字符出现的次数,然后搜索计数为1的第一个字符。

动态规划教程

动态编程是一种强大的算法技术,用于通过将复杂问题分解为更简单的子问题来解决复杂问题。让我们通过计算斐波那契数的示例来探讨这个概念。

/** * calculates the nth fibonacci number using dynamic programming. * @param {number} n - the position of the fibonacci number to calculate. * @returns {number} the nth fibonacci number. */function fibonacci(n) {  // initialize an array to store fibonacci numbers  const fib = new array(n + 1);  // base cases  fib[0] = 0;  fib[1] = 1;  console.log(`f(0) = ${fib[0]}`);  console.log(`f(1) = ${fib[1]}`);  // calculate fibonacci numbers iteratively  for (let i = 2; i <= n; i++) {    fib[i] = fib[i - 1] + fib[i - 2];    console.log(`f(${i}) = ${fib[i]}`);  }  return fib[n];}// example usageconst n = 10;console.log(`the ${n}th fibonacci number is:`, fibonacci(n));

此示例演示了动态编程如何通过存储先前计算的值并将其用于将来的计算来有效地计算斐波那契数。

二分查找教程

二分搜索是一种在排序数组中查找元素的有效算法。这是带有详细日志记录的实现:

/** * performs a binary search on a sorted array. * @param {number[]} arr - the sorted array to search. * @param {number} target - the value to find. * @returns {number} the index of the target if found, or -1 if not found. */function binarysearch(arr, target) {  let left = 0;  let right = arr.length - 1;  while (left <= right) {    const mid = math.floor((left + right) / 2);    console.log(`searching in range [${left}, ${right}], mid = ${mid}`);    if (arr[mid] === target) {      console.log(`target ${target} found at index ${mid}`);      return mid;    } else if (arr[mid] < target) {      console.log(`${arr[mid]}  ${target}, searching left half`);      right = mid - 1;    }  }  console.log(`target ${target} not found in the array`);  return -1;}// example usageconst sortedarray = [1, 3, 5, 7, 9, 11, 13, 15];const target = 7;binarysearch(sortedarray, target);

此实现展示了二分搜索如何在每次迭代中有效地将搜索范围缩小一半,使其比大型排序数组的线性搜索快得多。

深度优先搜索(dfs)广度优先搜索(bfs)堆(优先级队列)trie(前缀树)并查(不相交集)拓扑排序

深度优先搜索 (dfs)

深度优先搜索是一种图遍历算法,在回溯之前沿着每个分支尽可能地探索。以下是表示为邻接列表的图的示例实现:

class graph {  constructor() {    this.adjacencylist = {};  }  addvertex(vertex) {    if (!this.adjacencylist[vertex]) this.adjacencylist[vertex] = [];  }  addedge(v1, v2) {    this.adjacencylist[v1].push(v2);    this.adjacencylist[v2].push(v1);  }  dfs(start) {    const result = [];    const visited = {};    const adjacencylist = this.adjacencylist;    (function dfshelper(vertex) {      if (!vertex) return null;      visited[vertex] = true;      result.push(vertex);      console.log(`visiting vertex: ${vertex}`);      adjacencylist[vertex].foreach(neighbor => {        if (!visited[neighbor]) {          console.log(`exploring neighbor: ${neighbor} of vertex: ${vertex}`);          return dfshelper(neighbor);        } else {          console.log(`neighbor: ${neighbor} already visited`);        }      });    })(start);    return result;  }}// example usageconst graph = new graph();['a', 'b', 'c', 'd', 'e', 'f'].foreach(vertex => graph.addvertex(vertex));graph.addedge('a', 'b');graph.addedge('a', 'c');graph.addedge('b', 'd');graph.addedge('c', 'e');graph.addedge('d', 'e');graph.addedge('d', 'f');graph.addedge('e', 'f');console.log(graph.dfs('a'));

广度优先搜索 (bfs)

bfs 会探索当前深度的所有顶点,然后再移动到下一个深度级别的顶点。这是一个实现:

class graph {  // ... (same constructor, addvertex, and addedge methods as above)  bfs(start) {    const queue = [start];    const result = [];    const visited = {};    visited[start] = true;    while (queue.length) {      let vertex = queue.shift();      result.push(vertex);      console.log(`visiting vertex: ${vertex}`);      this.adjacencylist[vertex].foreach(neighbor => {        if (!visited[neighbor]) {          visited[neighbor] = true;          queue.push(neighbor);          console.log(`adding neighbor: ${neighbor} to queue`);        } else {          console.log(`neighbor: ${neighbor} already visited`);        }      });    }    return result;  }}// example usage (using the same graph as in dfs example)console.log(graph.bfs('a'));

堆(优先队列)

堆是一种满足堆性质的特殊的基于树的数据结构。这是最小堆的简单实现:

class minheap {  constructor() {    this.heap = [];  }  getparentindex(i) {    return math.floor((i - 1) / 2);  }  getleftchildindex(i) {    return 2 * i + 1;  }  getrightchildindex(i) {    return 2 * i + 2;  }  swap(i1, i2) {    [this.heap[i1], this.heap[i2]] = [this.heap[i2], this.heap[i1]];  }  insert(key) {    this.heap.push(key);    this.heapifyup(this.heap.length - 1);  }  heapifyup(i) {    let currentindex = i;    while (this.heap[currentindex] < this.heap[this.getparentindex(currentindex)]) {      this.swap(currentindex, this.getparentindex(currentindex));      currentindex = this.getparentindex(currentindex);    }  }  extractmin() {    if (this.heap.length === 0) return null;    if (this.heap.length === 1) return this.heap.pop();    const min = this.heap[0];    this.heap[0] = this.heap.pop();    this.heapifydown(0);    return min;  }  heapifydown(i) {    let smallest = i;    const left = this.getleftchildindex(i);    const right = this.getrightchildindex(i);    if (left < this.heap.length && this.heap[left] < this.heap[smallest]) {      smallest = left;    }    if (right < this.heap.length && this.heap[right]  minheap.insert(num));console.log(minheap.heap);console.log(minheap.extractmin());console.log(minheap.heap);

trie(前缀树)

trie 是一种高效的信息检索数据结构,常用于字符串搜索:

class trienode {  constructor() {    this.children = {};    this.isendofword = false;  }}class trie {  constructor() {    this.root = new trienode();  }  insert(word) {    let current = this.root;    for (let char of word) {      if (!current.children[char]) {        current.children[char] = new trienode();      }      current = current.children[char];    }    current.isendofword = true;    console.log(`inserted word: ${word}`);  }  search(word) {    let current = this.root;    for (let char of word) {      if (!current.children[char]) {        console.log(`word ${word} not found`);        return false;      }      current = current.children[char];    }    console.log(`word ${word} ${current.isendofword ? 'found' : 'not found'}`);    return current.isendofword;  }  startswith(prefix) {    let current = this.root;    for (let char of prefix) {      if (!current.children[char]) {        console.log(`no words start with ${prefix}`);        return false;      }      current = current.children[char];    }    console.log(`found words starting with ${prefix}`);    return true;  }}// example usageconst trie = new trie();['apple', 'app', 'apricot', 'banana'].foreach(word => trie.insert(word));trie.search('app');trie.search('application');trie.startswith('app');trie.startswith('ban');

并查集(不相交集)

union-find 是一种数据结构,用于跟踪被分成一个或多个不相交集合的元素:

class unionfind {  constructor(size) {    this.parent = array(size).fill().map((_, i) => i);    this.rank = array(size).fill(0);    this.count = size;  }  find(x) {    if (this.parent[x] !== x) {      this.parent[x] = this.find(this.parent[x]);    }    return this.parent[x];  }  union(x, y) {    let rootx = this.find(x);    let rooty = this.find(y);    if (rootx === rooty) return;    if (this.rank[rootx] < this.rank[rooty]) {      [rootx, rooty] = [rooty, rootx];    }    this.parent[rooty] = rootx;    if (this.rank[rootx] === this.rank[rooty]) {      this.rank[rootx]++;    }    this.count--;    console.log(`united ${x} and ${y}`);  }  connected(x, y) {    return this.find(x) === this.find(y);  }}// example usageconst uf = new unionfind(10);uf.union(0, 1);uf.union(2, 3);uf.union(4, 5);uf.union(6, 7);uf.union(8, 9);uf.union(0, 2);uf.union(4, 6);uf.union(0, 4);console.log(uf.connected(1, 5)); // should print: trueconsole.log(uf.connected(7, 9)); // should print: false

拓扑排序

拓扑排序用于对具有依赖关系的任务进行排序。这是使用 dfs 的实现:

class Graph {  constructor() {    this.adjacencyList = {};  }  addVertex(vertex) {    if (!this.adjacencyList[vertex]) this.adjacencyList[vertex] = [];  }  addEdge(v1, v2) {    this.adjacencyList[v1].push(v2);  }  topologicalSort() {    const visited = {};    const stack = [];    const dfsHelper = (vertex) => {      visited[vertex] = true;      this.adjacencyList[vertex].forEach(neighbor => {        if (!visited[neighbor]) {          dfsHelper(neighbor);        }      });      stack.push(vertex);      console.log(`Added ${vertex} to stack`);    };    for (let vertex in this.adjacencyList) {      if (!visited[vertex]) {        dfsHelper(vertex);      }    }    return stack.reverse();  }}// Example usageconst graph = new Graph();['A', 'B', 'C', 'D', 'E', 'F'].forEach(vertex => graph.addVertex(vertex));graph.addEdge('A', 'C');graph.addEdge('B', 'C');graph.addEdge('B', 'D');graph.addEdge('C', 'E');graph.addEdge('D', 'F');graph.addEdge('E', 'F');console.log(graph.topologicalSort());

这些实现为在编码面试和实际应用中理解和使用这些重要的算法和数据结构提供了坚实的基础。

以上就是编码面试中解决问题的终极指南的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1491638.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月19日 14:08:28
下一篇 2025年12月19日 14:08:39

相关推荐

  • JavaScript 中的对象

    有键值对,用冒号分隔。密钥也称为属性相似之处:数组的索引被对象中的键替换。对象字面量语法是直接在 {} 中写入属性对于对象来说,检索期间的顺序并不重要,而对于数组来说,顺序很重要。 数组:用于结构化数据对象:用于非结构化数据 对象中的属性查找方法: 使用点表示法使用方括号表示法:键定义为引号内 []…

    2025年12月19日
    000
  • 理解 JavaScript 中的对象

    您是否遇到过需要在 javascript 代码中存储一组复杂信息的情况?例如,您需要将用户的数据存储在数据库中,例如姓名、年龄和地址。您将使用什么 javascript 框架来完成此任务? 在本文中,我们将了解对象如何在此类任务中发挥作用,并了解 javascript 中这一重要数据集合的含义。 跟…

    2025年12月19日
    000
  • JavaScript 基础知识:第 1 部分

    javascript 就像一罐蜂蜜。您可以将手指浸入其中并刷一口。很甜。太棒了。这是危险的。它可能很危险,就像锅里的热蜂蜜一样。 javascript 复杂吗?好吧,您应该在本摘录的末尾找到这个问题的答案(也包括其他部分)。我们可以问另一个问题。开发一个程序需要多少 javascript 知识?如果…

    2025年12月19日
    000
  • 每个开发人员都应该了解的基本 Express 请求属性

    在项目后端工作时,处理请求和响应至关重要。有效管理这些请求对于客户端和服务器之间的顺利通信至关重要。以下是每个开发人员都应该熟悉的一些常见且重要的请求属性。 1. 请求ip express.js 中的 req.ip 是请求对象的一个​​属性,它提供发出请求的客户端的 ip 地址。它返回一个代表客户端…

    2025年12月19日
    000
  • Redis:内存数据结构存储终极指南

    redis 是不断发展的数据管理和存储领域中广泛使用的技术。 redis 被公认为内存中数据结构存储,它提供了广泛的功能,使其成为从缓存到实时分析等各种应用程序的标准基础。这个综合教程将介绍 redis 是什么、它的核心功能、用例以及如何开始。 什么是redis? redis代表远程字典服务器;它是…

    2025年12月19日
    000
  • 电子书

    es6 (ecmascript 2015) 为 javascript 引入了多项新功能和语法改进。以下是最重要的 es6 语法的总结和示例: 1. let 和 const 关键字 es6 为块作用域变量引入了 let 和 const。 let:块范围变量,可以更新,但不能在同一范围内重新声明。con…

    2025年12月19日
    000
  • 利用 JavaScript 的集合和映射实现高效的内容管理系统

    javascript 提供了几种强大的数据结构来处理数据集合。其中,map 和 set 对于某些类型的任务特别有用。在本博客中,我们将探讨使用 map 和 set 解决常见编程问题的现实示例。 理解地图和集合在深入示例之前,让我们快速回顾一下 javascript 中的 map 和 set 是什么。…

    2025年12月19日
    000
  • 差异 JSON:综合指南

    JSON(JavaScript 对象表示法)由于其简单性和可读性,已成为 Web 应用程序中数据交换的标准。 JSON 的结构由键值对、数组和对象组成,使其成为表示复杂数据结构的理想格式。因此,它被广泛应用于 API、配置文件和数据存储中。然而,随着应用程序变得越来越复杂,比较 JSON 数据的需求…

    2025年12月19日
    000
  • 循环:For 循环、While 循环、ForOf 循环、ForIn 循环

    循环的目的是重复一些功能。 一些类型的循环包括: for 循环while 循环for…of 循环for…循环 for循环 to 可以写一个简单的 for 循环如下: for (let i = 1; i <= 10; i++) { console.log(i); // p…

    2025年12月19日
    000
  • C++如何实现一个可配置的系统_使用ini-parser或jsoncpp为C++应用添加配置文件功能

    通过引入INI或JSON外部配置文件,结合SimpleIni或JsonCpp库解析,可实现C++项目的灵活配置管理,提升可维护性与扩展性。 在C++项目中,硬编码配置参数会让程序难以维护和扩展。通过引入外部配置文件(如INI或JSON格式),可以实现灵活的可配置系统。以下是使用 ini-parser…

    2025年12月19日
    000
  • c++如何实现一个简单的后缀数组(Suffix Array)_c++字符串处理高级算法【源码】

    c++kquote>后缀数组是字符串所有后缀按字典序排序后的起始下标数组;例如”ababa”的后缀数组为[4,0,2,1,3];可通过暴力法(O(n²log n))或倍增算法(O(n log²n))构建,后者利用rank数组分轮按长度倍增排序。 什么是后缀数组? 后缀数…

    2025年12月19日
    000
  • c++ map和unordered_map区别 c++哈希表性能对比

    map基于红黑树实现,元素有序,操作时间复杂度为O(log n);unordered_map基于哈希表,无序,平均O(1)最坏O(n)。前者适用于需排序场景,后者适合追求高效查找且无需顺序的场合。 在C++中,map 和 unordered_map 都是标准库提供的关联容器,用于存储键值对。虽然它们…

    2025年12月19日
    000
  • C++如何使用map(映射)?(入门教程)

    C++中map是基于红黑树的有序关联容器,按键升序存储键值对,支持O(log n)查找/插入/删除;需#include ,声明为std::map,常用[]、insert、emplace插入,find安全访问,范围for遍历。 在C++中,map 是一种关联容器,用来存储“键-值”对(key-valu…

    2025年12月19日
    000
  • C++如何与Lua交互?C++嵌入Lua脚本引擎教程【混合编程】

    C++嵌入Lua核心是纯C API操作栈:初始化状态机并加载脚本;C++调用Lua函数需压参、pcall、取返回值;注册C函数供Lua调用;用userdata封装复杂数据并配元表;全程注意栈平衡。 用C++嵌入Lua,核心是调用Lua C API完成栈操作、函数调用和数据交换。不依赖第三方绑定库(如…

    2025年12月19日
    000
  • C++如何实现一个简单的INI配置文件解析器?(代码示例)

    C++ INI解析器用嵌套map存储“节→键→值”,逐行读取并处理注释、节定义和键值对,支持trim、get、get_int等接口。 用 C++ 实现一个简单的 INI 解析器,核心是按行读取、识别节([section])、键值对(key=value)和注释,并把数据存进内存结构中。不需要依赖第三方…

    2025年12月19日
    000
  • c++如何读写JSON文件_c++集成jsoncpp库进行数据解析

    使用jsoncpp库可高效读写JSON文件。首先通过包管理器或源码安装jsoncpp,再在C++项目中包含头文件并链接库。读取时用Json::CharReaderBuilder解析文件内容到Json::Value对象,写入时用Json::StreamWriterBuilder将Json::Value…

    2025年12月19日
    000
  • C++ map如何按value排序_C++ map自定义排序规则实现步骤

    std::map按key排序,需通过vector+sort或multimap实现按value排序:1. 将map转为vector后用自定义比较函数排序;2. 使用multimap插入value-key对利用其自动排序;3. 可封装通用函数提高复用性。 在C++中,std::map 默认是按照 key…

    2025年12月19日
    000
  • C++如何使用unordered_map?(哈希表用法)

    unordered_map 是 C++ 基于哈希表的关联容器,平均时间复杂度 O(1),不保证顺序;需支持 == 和 std::hash;常用 insert/find 避免下标意外插入;自定义类型作 key 需提供哈希与相等函数。 unordered_map 是 C++ 标准库中基于哈希表实现的关联…

    2025年12月19日
    000
  • C++如何实现一个简单的数据库索引_使用C++ B+树实现高效数据检索

    B+树因有序性和高效I/O被广泛用于数据库索引。2. 其节点分内部与叶子,支持插入、删除、查找和范围查询。3. 插入时通过分裂维持平衡,查找逐层定位,叶子间链表支持范围扫描。4. C++实现以模板化键类型和指针管理构建核心结构,适合内存中高效检索与小型数据库应用。 在C++中实现一个简单的数据库索引…

    2025年12月19日
    000
  • 如何用C++写一个INI配置文件解析器?C++文件IO与字符串处理实战【项目练习】

    C++轻量级INI解析器使用标准库实现:按行读取文件,识别节名([section])、键值对(key=value),跳过注释与空行,自动trim两端空格,用嵌套map存储配置,支持config”section”访问。 用C++写一个轻量级INI解析器,核心在于:按行读取、识别…

    2025年12月19日
    000

发表回复

登录后才能评论
关注微信