2024-08-15

题目:二维数组中的查找

在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

示例:

现有矩阵 matrix 如下:

[

[1, 4, 7, 11, 15],

[2, 5, 8, 12, 19],

[3, 6, 9, 16, 22],

[10, 13, 14, 17, 24],

[18, 21, 23, 26, 30]

]

给定 target = 5,返回 true。

给定 target = 20,返回 false。

解法1:




function findNumberIn2DArray(matrix: number[][], target: number): boolean {
  for (let i = 0; i < matrix.length; i++) {
    for (let j = 0; j < matrix[i].length; j++) {
      if (matrix[i][j] === target) {
        return true;
      }
    }
  }
  return false;
}

解法2:




function findNumberIn2DArray(matrix: number[][], target: number): boolean {
  let row = matrix.length - 1, col = 0;
  while (row >= 0 && col < matrix[0].length) {
    if (matrix[row][col] === target) return true;
    else if (matrix[row][col] > target) row--;
    else col++;
  }
  return false;
}
2024-08-15

由于提问中已经包含了完整的代码实例和解释,这里我们只简要提供关键信息和代码实例。

  1. container/list:双向链表实现。



l := list.New()
l.PushBack("world")
l.PushFront("hello")
for e := l.Front(); e != nil; e = e.Next() {
    fmt.Print(e.Value, " ")
}
// 输出: hello world
  1. sort:排序算法。



ints := []int{4, 2, 3, 1}
sort.Ints(ints)
fmt.Println(ints) // 输出: [1 2 3 4]
  1. strings:字符串操作函数。



fmt.Println(strings.Contains("test", "es")) // 输出: true
  1. math/rand:随机数生成。



rand.Seed(time.Now().UnixNano())
fmt.Println(rand.Intn(10)) // 输出: 0-9之间的一个随机整数
  1. imageimage/colorimage/png:图像处理。



rect := image.Rect(0, 0, 100, 100)
img := image.NewNRGBA(rect)
for y := 0; y < 100; y++ {
    for x := 0; x < 100; x++ {
        img.Set(x, y, color.RGBA{uint8(x), uint8(y), 0, 255})
    }
}
png.Encode(os.Stdout, img) // 将图像编码并输出到标准输出
  1. encoding/json:JSON处理。



type Message struct {
    Name string
    Body string
    Time int64
}
m := Message{"Alice", "Hello", 1294706395881547000}
b, _ := json.Marshal(m)
fmt.Println(string(b)) // 输出: {"Name":"Alice","Body":"Hello","Time":1294706395881547000}

以上代码实例展示了Go语言中常用的数据结构、算法、IO操作、图像处理、编码和JSON处理等方面的用法。这些是学习Go语言必须掌握的核心库和技术。

2024-08-15

题目:删除排序链表中的重复元素

解法:遍历链表,并比较当前节点与下一节点的值,如果发现重复,则跳过下一节点并释放它。

Java 实现:




public class Solution {
    public ListNode deleteDuplicates(ListNode head) {
        if (head == null) {
            return head;
        }
 
        ListNode current = head;
        while (current.next != null) {
            if (current.val == current.next.val) {
                current.next = current.next.next;
            } else {
                current = current.next;
            }
        }
 
        return head;
    }
}

C 实现:




struct ListNode* deleteDuplicates(struct ListNode* head) {
    if (head == NULL) {
        return head;
    }
 
    struct ListNode* current = head;
    while (current->next != NULL) {
        if (current->val == current->next->val) {
            current->next = current->next->next;
        } else {
            current = current->next;
        }
    }
 
    return head;
}

Python3 实现:




class Solution:
    def deleteDuplicates(self, head: ListNode) -> ListNode:
        if not head:
            return head
 
        current = head
        while current.next:
            if current.val == current.next.val:
                current.next = current.next.next
            else:
                current = current.next
        return head

Go 实现:




/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func deleteDuplicates(head *ListNode) *ListNode {
    if head == nil {
        return head
    }
 
    current := head
    for current.Next != nil {
        if current.Val == current.Next.Val {
            current.Next = current.Next.Next
        } else {
            current = current.Next
        }
    }
 
    return head
}
2024-08-15

A*(A-Star)搜索算法是一种路径规划算法,它能够为网格或任何其他类型的图形中的任务节点找到最低成本的路径到目标节点。它是一种启发式搜索算法,使用了一个估价函数来评估从开始节点到任何给定节点的成本。

A*算法的特征:

  • 启发式搜索:A*算法使用了一种启发式,即它估计了每个节点到目标的距离,并选择了最有可能的节点进行下一步搜索。
  • 最低成本路径:A*算法保证找到最低成本的路径到目标节点。
  • 使用估价函数:A*算法使用了一个估价函数f(n) = g(n) + h(n),其中g(n)是从开始节点到当前节点的实际成本,h(n)是从当前节点到目标节点的估计成本。

A*算法的公式:

f(n) = g(n) + h(n)

  • g(n) 是从开始节点到当前节点的实际移动代价总和。
  • h(n) 是从当前节点到目标节点的估计移动代价总和。
  • f(n) 是从开始节点到当前节点的总估计移动代价。

Python示例代码(带详细注释):




class Node:
    def __init__(self, parent=None, position=None):
        self.parent = parent
        self.position = position
 
    def __repr__(self):
        return f"Node({self.position})"
 
def heuristic(node, end_node):
    # 这是一个简单的例子,通常使用Manhattan距离或欧氏距离
    return abs(node.position[0] - end_node.position[0]) + abs(node.position[1] - end_node.position[1])
 
def search(start_node, end_node):
    closed_set = set()
    open_set = {start_node}
 
    while open_set:
        current = min(open_set, key=lambda o: o.position)  # 选择f值最小的节点
        if current == end_node:
            path = []
            current = current.parent
            while current in closed_set:
                path.append(current.position)
                current = current.parent
            return path[::-1]  # 返回从开始节点到结束节点的路径
 
        open_set.remove(current)
        closed_set.add(current)
 
        for neighbor in current.neighbors:
            if neighbor in closed_set:
                continue
 
            neighbor.g = current.g + 1  # 设置g值为父节点的g值加一
            neighbor.h = heuristic(neighbor, end_node)  # 设置h值
            neighbor.parent = current
 
            if neighbor not in open_set:
                open_set.add(neighbor)
            else:
                if neighbor.g > current.g + 1:  # 更新g值
                    neighbor.g = current.g + 1
                    neighbor.parent = current
    return None
 
# 示例使用
start_node = Node(position=(0, 0))
end_node = Node(position=(4, 4))
# 假设neighbors是节点的邻居列表
start_node.neighbors = [Node(position=(0, 1)), Node(position=(1, 0))]
# ...为其他节点设置neighbors属性
path = search(start_node, end_node)
print(path)

这个Python示例代码定义了一个Node类来表示图中的节点,并提供了一个heuristic函数来估计从当

2024-08-15

CSS 优先级是由四个级别组成:

  1. 内联样式(Inline style)- 优先级最高,为 1000。
  2. ID 选择器(ID selectors)- 优先级为 0100。
  3. 类选择器(Class selectors)、属性选择器(Attribute selectors)和伪类(Pseudo-classes)- 优先级为 0010。
  4. 元素选择器(Type selectors)和伪元素(Pseudo-elements)- 优先级为 0001。

优先级计算时,将这四个级别的数值依次相加,然后比较数值大小。如果两个规则的优先级数值相同,则后定义的规则将会被应用。

例如,考虑以下两个选择器:




#myId .myClass > p { color: red; } /* 优先级 = 0100 + 0010 + 0001 = 1110 */
p#myId > .myClass { color: blue; } /* 优先级 = 0001 + 0100 + 0010 = 1100 */

根据优先级算法,p#myId > .myClass 的规则将会被应用,因为它的优先级更高(1100 > 1110)。

注意:继承的样式不参与优先级计算,并且被认为具有最低的优先级。

2024-08-15

排列组合是数学中的一个基本概念,主要有两种形式:排列和组合。

  1. 排列:排列是指将n个不同的元素,每个元素都有可能出现在每一个位置上。所以,对于n个元素的排列,总共有n!种可能。
  2. 组合:组合是指从n个不同的元素中,选取r个元素进行组合,这里不考虑顺序,所以,对于n个元素的组合,总共有C(n, r) = n! / (r! * (n-r)!)种可能。

以下是使用JavaScript实现排列和组合算法的示例代码:

  1. 排列算法:



function factorial(n) {
    if (n === 0 || n === 1) {
        return 1;
    }
    return n * factorial(n - 1);
}
 
function permutation(n, k) {
    return factorial(n) / factorial(n - k);
}
 
console.log(permutation(5, 3)); // 输出: 60

在上述代码中,factorial函数用于计算一个数的阶乘,permutation函数用于计算排列数。

  1. 组合算法:



function factorial(n) {
    if (n === 0 || n === 1) {
        return 1;
    }
    return n * factorial(n - 1);
}
 
function combination(n, k) {
    return factorial(n) / (factorial(k) * factorial(n - k));
}
 
console.log(combination(5, 3)); // 输出: 10

在上述代码中,combination函数用于计算组合数。

以上就是使用JavaScript实现排列和组合算法的简单示例。

2024-08-15

题目描述:

给定一个字符串,请设计一个算法,将字符串中的所有空格替换成 "%20" 。

解决方案:

  1. Java 解法:



public class Solution {
    public String replaceSpaces(StringBuffer str) {
        return str.toString().replace(" ", "%20");
    }
}
  1. JavaScript 解法:



function replaceSpaces(str) {
    return str.replace(/ /g, '%20');
}
  1. Python 解法:



class Solution:
    def replaceSpaces(self , S: str) -> str:
        return S.replace(' ', '%20')
  1. C 解法:



#include <stdio.h>
#include <string.h>
 
void replaceSpaces(char str[]) {
    int i, j, len = strlen(str);
    for (i = j = 0; i < len; i++) {
        if (str[i] == ' ') {
            str[j++] = '%';
            str[j++] = '2';
            str[j++] = '0';
        } else {
            str[j++] = str[i];
        }
    }
    str[j] = '\0'; // 不要忘记添加结束符
}
 
int main() {
    char str[] = "Hello World!";
    replaceSpaces(str);
    printf("%s", str);
    return 0;
}
  1. C++ 解法:



#include <iostream>
#include <string>
#include <algorithm>
 
std::string replaceSpaces(std::string str) {
    std::replace(str.begin(), str.end(), ' ', '%20');
    return str;
}
 
int main() {
    std::string str = "Hello World!";
    std::string replacedStr = replaceSpaces(str);
    std::cout << replacedStr;
    return 0;
}

以上代码提供了不同语言的实现方法,主要使用了字符串替换的方法。对于 Java 和 JavaScript,使用了 String 类的 replace 方法;对于 Python,使用了 str 的 replace 方法;对于 C 和 C++,使用了标准库中的算法 replace。

2024-08-14

滑动窗口算法是一种用于处理字符串或数组中子串问题的高效方法。它通过维护一个窗口,在遍历字符串或数组的过程中,不断更新窗口大小,从而找出满足条件的子串或子序列。

在LeetCode上,滑动窗口算法常见于以下问题类型:

  1. 子串问题:找出字符串中最长/最短的子串满足某种条件。
  2. 字符统计:计算字符串中字符出现的次数。
  3. 字母异位词:判断两个字符串是否由相同的字母构成,可以考虑使用滑动窗口。

以下是一些使用滑动窗口解决的经典问题:

  • 无重复字符的最长子串
  • 滑动窗口最大值
  • 最小滑动窗口范围
  • 滑动窗口中的最大值

解决这些问题通常需要设置两个指针,一个代表窗口的开始,另一个代表窗口的结束,根据需要更新窗口的大小或移动窗口。

以下是无重复字符的最长子串的示例代码:




class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        # 使用哈希集合记录字符是否出现过
        occ = set()
        n = len(s)
        # 右指针,初始值为-1表示还没有开始移动
        rk, ans = -1, 0
        for i in range(n):
            if i != 0:
                # 左指针向右移动
                occ.remove(s[i - 1])
            while rk + 1 < n and s[rk + 1] not in occ:
                # 不断扩大窗口直到出现重复字符
                occ.add(s[rk + 1])
                rk += 1
            # 更新最长无重复子串的长度
            ans = max(ans, rk - i + 1)
        return ans

滑动窗口算法是一种非常实用的技巧,可以解决许多字符串和数组问题。理解和熟练运用该算法对于高效解决编程问题至关重要。

2024-08-14

在Java中使用雪花算法生成全局唯一ID的示例代码如下:




import java.util.concurrent.atomic.AtomicLong;
 
public class SnowflakeIdGenerator {
    // 64位ID的各个部分所占的位数
    private final long twepoch = 1288834974657L; // 起始时间戳 (2010-11-04 09:42:54.657)
    private final long workerIdBits = 5L; // 工作机器ID所占的位数
    private final long datacenterIdBits = 5L; // 数据中心ID所占的位数
    private final long sequenceBits = 12L; // 序列号所占的位数
 
    // 这些位都是直接按位或(|)运算,所以这里需要左移运算符(<<)
    private final long workerIdShift = sequenceBits;
    private final long datacenterIdShift = sequenceBits + workerIdBits;
    private final long timestampShift = sequenceBits + workerIdBits + datacenterIdBits;
 
    private final long sequenceMask = -1L ^ (-1L << sequenceBits); // 生成序列的掩码
 
    private long workerId; // 工作机器ID
    private long datacenterId; // 数据中心ID
    private long sequence = 0L; // 序列号
    private long lastTimestamp = -1L; // 上一次生成ID的时间戳
 
    private AtomicLong id = new AtomicLong(0);
 
    // 构造函数,传入工作机器ID和数据中心ID
    public SnowflakeIdGenerator(long workerId, long datacenterId) {
        if (workerId > maxWorkerId || workerId < 0) {
            throw new IllegalArgumentException("workerId can't be greater than %d or less than 0");
        }
        if (datacenterId > maxDatacenterId || datacenterId < 0) {
            throw new IllegalArgumentException("datacenterId can't be greater than %d or less than 0");
        }
        this.workerId = workerId;
        this.datacenterId = datacenterId;
    }
 
    // 生成下一个ID
    public synchronized long nextId() {
        long timestamp = timeGen();
 
        if (timestamp < lastTimestamp) {
            throw new RuntimeException(String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
        }
 
        if (lastTimestamp == timestamp) {
            sequence = (sequence + 1) & sequenceMask;
            if (sequence == 0) {
                timestamp = tilNextMillis(lastTimestamp);
            }
        } else {
            sequence = 0;
        }
 
        lastTimestamp = timestamp;
 
        id.set((timestamp - twepoch) << timestampShift | (datacenterId << datacenterIdShift) | (workerId << workerIdShift) | sequence);
        return id.get();
    }
 
    // 获取当前时间戳
    protected long timeGen() {
        return System.currentTimeMillis();
    }
 
    // 等待下一个毫秒的到来,用于解决时钟回拨问题
    protected long tilNextMil