Timothyoung97 / RenderingEngine

0 stars 0 forks source link

Hoyo GPP Prep #5

Open Timothyoung97 opened 3 months ago

Timothyoung97 commented 3 months ago

This issue comprises of some preparation contents made for interviews

Timothyoung97 commented 3 months ago

Networking Question

OSI

image

Address Resolution Protocol (ARP)

image

Swtich vs Router, IP vs MAC

image image

Link Layer

image

Cyclic Redundancy Check (CRC32) MAC Address

image

Internet Control Message Protocol (ICMP) Network Layer

image

IPv4

image

NAT

image

RIP

image

IP Addr

Screenshot 2024-04-11 at 11 06 36 AM

Dynamic Host Configuration Protocol (APP layer, runs on UDP)

Screenshot 2024-04-11 at 10 48 18 AM

Also provides details IP of:


UDP vs TCP

TCP (Transmission Control Protocol) and UDP (User Datagram Protocol) are two widely used transport layer protocols in computer networks. Here are the main differences between TCP and UDP:

In summary, TCP provides reliable, ordered, and connection-oriented communication with additional overhead and mechanisms for error recovery and flow control. UDP, on the other hand, offers faster and connectionless communication with minimal overhead but lacks reliability and error recovery mechanisms. The choice between TCP and UDP depends on the specific requirements of the application, such as the importance of reliability, latency, and speed.

Screenshot 2024-04-11 at 10 27 58 AM image image

Port Num

Here are some common examples of port numbers and their typical usage:

These are just a few examples of common port numbers and their associated protocols. Different applications and services use specific port numbers for communication, and understanding these port numbers can help in network configuration and troubleshooting.


DNS Resource Record

DNS(Domain Name System)记录是DNS服务器上存储的数据项,用于将域名解析为对应的IP地址或其他网络服务信息。常见的DNS记录类型包括:

这些DNS记录类型可以组合使用,以实现域名到IP地址的解析、邮件传递、服务发现等功能。通过管理DNS记录,可以控制域名的解析行为和网络服务的路由,保证网络通信的正常进行。

What happens after you enter www.google.com

在浏览器中输入并按下“www.google.com”后,通常会经历以下步骤才能显示谷歌的网页:

整个过程包括了DNS解析、建立TCP连接、发送HTTP请求、服务器处理请求、接收和解析响应、页面渲染和显示页面等步骤,确保用户能够顺利访问和浏览网页内容。


User Verification

游戏客户端实现用户身份验证或会话管理等功能通常涉及以下步骤和技术:

上述流程是一个简化的用户身份验证和会话管理的实现过程。实际应用中,还可能涉及到一些安全性和稳定性的考虑,比如使用HTTPS协议保证通信安全、使用加密算法保护用户密码和会话令牌、处理会话过期和异常情况等。


Cookie

游戏客户端可能会使用Cookie来实现一些功能或记录一些信息,但与网站应用不同,游戏客户端通常不会使用Cookie来实现用户身份验证或会话管理等功能。下面是一些游戏客户端可能会使用的Cookie类型:

需要注意的是,游戏客户端通常不会使用Cookie来存储敏感信息,如用户密码等。对于敏感信息的处理,游戏客户端通常会使用更安全的方式,比如加密存储、安全传输等。


HTTP Reponse

HTTP响应状态码是指在客户端发送请求后,服务器返回的表示请求处理结果的数字代码。状态码通常分为以下几个类别:

这些状态码在HTTP协议中有明确的规定,客户端和服务器可以根据不同的状态码进行相应的处理和反馈,以确保通信过程的正常进行和信息的正确传递。


TCP Triple Handshake

TCP 三次握手(three-way handshake)对于建立可靠的网络连接至关重要。这个过程确保了通信双方的同步和可靠性,以下是其重要性:

总体来说,TCP 三次握手确保了通信的可靠性和顺序性,对于构建稳定的网络连接至关重要。


TCP 4 times handshake

TCP 的四次握手(four-way handshake)是在连接关闭时的重要过程,它确保了连接的可靠关闭和资源释放。以下是四次握手的重要性:

综上所述,TCP 四次握手是确保连接可靠关闭和资源释放的重要步骤,对于网络通信的稳定性和效率至关重要。


DIff HTTPS vs. HTTP

HTTPS(Hypertext Transfer Protocol Secure)和 HTTP(Hypertext Transfer Protocol)是用于在网络上传输数据的两种协议,它们之间的主要区别包括以下几点:

综上所述,HTTPS相对于HTTP更安全、更可信,适合传输敏感数据和进行安全的网络通信。


Diff TCP vs HTTPS

TCP (Transmission Control Protocol) and HTTPS (Hypertext Transfer Protocol Secure) are different protocols used in computer networking, and they serve different purposes.

TCP (Transmission Control Protocol):
HTTPS (Hypertext Transfer Protocol Secure):

In summary, TCP is a lower-level protocol responsible for reliable data transmission, while HTTPS is a higher-level protocol that adds security features, including encryption, to the communication process between clients and servers, typically used in web browsing and secure online transactions.


Multiplayer Game Arch

多人网游游戏实现多人同步通常采用以下技术和策略:

综合利用这些技术和策略,多人网游可以实现较好的多人同步效果,保证玩家在游戏中获得良好的体验和互动性。


Debug Networking

判断从服务器到客户端导致客户端接收不到更新的问题可以采取以下步骤:

通过以上方法结合调试和分析,可以逐步定位问题所在,找出导致客户端接收不到更新的具体原因,并进行相应的修复和优化。


问怎么理解粘包,如何解决(完全不懂)

Timothyoung97 commented 3 months ago

Security Question

反作弊软件是一种专门设计用于防止游戏作弊行为的软件。它们通常结合了多种技术和策略,旨在监控游戏进程、检测作弊程序,并采取相应的防御措施。下面是反作弊软件通常采取的一些技术和方法:

总的来说,反作弊软件通过监控、检测、识别和防御等多种技术手段,来防止游戏中的作弊行为,维护游戏的公平性和竞技性。这些技术通常需要不断更新和改进,以应对不断演变的作弊手段和挑战。

Timothyoung97 commented 3 months ago

Gameplay Question

游戏3C是指游戏中的三个重要要素,即Character(角色)、Camera(摄像机)和Control(控制)。这些要素在游戏设计和开发中扮演着关键的角色,影响着玩家的游戏体验和游戏的可玩性。

游戏3C的设计需要综合考虑角色的特性、摄像机的视角和控制方式,以提供丰富、流畅、易于操作的游戏体验。良好的游戏3C设计可以增强游戏的沉浸感、可玩性和乐趣,是游戏开发中重要的方面之一。


对于设计一个范围性的攻击,可以使用设计模式中的命令模式(Command Pattern)来实现。命令模式可以将请求封装成一个对象,从而允许将请求的发送者和接收者解耦,同时支持对请求的参数化和队列化操作。

以下是使用命令模式设计范围性攻击的一种实现方式:

public interface Command {
    void execute();
}
public class RangeAttackCommand implements Command {
    private int damage;
    private int range;
    private List<Character> targets;

    public RangeAttackCommand(int damage, int range, List<Character> targets) {
        this.damage = damage;
        this.range = range;
        this.targets = targets;
    }

    @Override
    public void execute() {
        for (Character target : targets) {
            // 对目标造成伤害
            target.takeDamage(damage);
        }
    }
}
public class Player {
    private Command rangeAttackCommand;

    public void setRangeAttackCommand(Command command) {
        this.rangeAttackCommand = command;
    }

    public void performRangeAttack() {
        if (rangeAttackCommand != null) {
            rangeAttackCommand.execute();
        }
    }
}
// 创建玩家对象和敌人列表
Player player = new Player();
List<Character> enemies = new ArrayList<>();
enemies.add(new Enemy());
enemies.add(new Enemy());

// 创建范围攻击命令并设置给玩家
Command rangeAttack = new RangeAttackCommand(50, 5, enemies);
player.setRangeAttackCommand(rangeAttack);

// 玩家发起范围攻击
player.performRangeAttack();

通过上述设计,使用命令模式可以有效地实现范围性攻击,将攻击请求和执行解耦,并支持灵活的参数化操作,提高了游戏系统的可扩展性和可维护性。

Timothyoung97 commented 3 months ago

Game Engine Usage

Perf Optimisation

游戏变得卡顿可能有多种原因,以下从游戏引擎的角度进行分析可能的原因:

综上所述,游戏卡顿可能是由于性能瓶颈、内存管理问题、渲染优化不足、脚本执行效率低下、资源管理问题等多种因素导致的。需要通过性能分析工具和调试工具来定位具体的问题,并采取相应的优化措施来提升游戏的性能和流畅度。


Collision

在游戏引擎中判断手雷弹的攻击范围内是否包括敌人通常可以通过碰撞检测和区域检测来实现。以下是一些常见的方法:

这些方法可以结合使用,根据游戏的具体需求和场景来选择合适的检测方式。例如,在实时性要求高的游戏中,可以使用快速的碰撞检测方法;而在需要精确判断的情况下,可以使用射线检测或区域检测等方法。


ECS

ECS(Entity-Component-System)是一种游戏引擎常用的设计模式,它将游戏对象拆分成实体(Entity)、组件(Component)和系统(System),每个部分都有特定的责任和功能。以下是游戏引擎使用ECS设计的一些原因:

总的来说,游戏引擎使用ECS设计模式能够提高游戏的性能、灵活性和可维护性,适合于复杂的游戏项目开发和管理。


ECS

想象一下你正在开发一个城市建设类的游戏,其中有各种不同类型的建筑物,比如住宅区、商业区、工业区等。你可以使用ECS设计模式来管理这些建筑物。

实体(Entity): 在游戏中,每个建筑物可以作为一个实体。例如,一个住宅区实体代表一个住宅区建筑物。

组件(Component): 每种建筑物都有不同的属性和特征,这些可以表示为组件。比如,建筑物可以有“位置”组件表示其在游戏世界中的坐标位置,还可以有“生产力”组件表示其每天产生的资源数量。

系统(System): 系统负责管理组件和处理游戏逻辑。比如,你可以有一个“建筑物管理系统”,它负责管理所有建筑物的生命周期、资源产出、交互等。另外,你可以有一个“交互系统”,负责处理玩家与建筑物的交互,比如点击建筑物显示详细信息、升级建筑物等。

通过ECS设计模式,你可以轻松地添加新的建筑物类型或调整现有的建筑物属性,而不会影响其他部分的代码。比如,你可以添加一个新的“公园”建筑物类型,只需要创建对应的实体并添加相应的组件即可,而无需修改现有的系统代码。

这样的设计使得游戏开发更加灵活、可扩展,同时也提高了代码的可维护性和可读性,适用于需要管理大量复杂实体和交互的游戏项目。

Timothyoung97 commented 3 months ago

Graphics Question

手游通常不使用延迟渲染(Deferred Rendering)的主要原因是出于性能和资源管理的考虑。延迟渲染是一种高级的渲染技术,它能够处理大量的光照和材质细节,但在移动设备上实现延迟渲染可能存在以下挑战:

因此,为了在移动设备上获得更好的性能和用户体验,手游通常会选择更轻量级的渲染技术,如提前渲染(Forward Rendering)、简化的光照模型、减少渲染通道等,以确保游戏在移动设备上运行流畅且效果良好。


Rendering Techniques used in Genshin Impact For Console https://www.docswell.com/s/UnityJapan/KWRPQ5-210617-unity-dojo20211mihoyozhenzhongyi#p1


Instanced Rendering(实例化渲染)是一种用于优化渲染性能的技术,特别适用于需要大量重复对象的场景,比如在游戏中大量相同模型的渲染。

实例化渲染的优化性能主要体现在以下几个方面:

总的来说,实例化渲染通过减少绘制调用、顶点数据传输、渲染状态切换等开销,充分利用GPU硬件的并行处理能力,从而优化了渲染性能,特别适用于大规模重复对象的渲染场景,如森林中的树木、城市中的建筑等。

Timothyoung97 commented 3 months ago

C++ Questions

++i和i++的区别,作为类的成员函数重载时候前置++和后置++有啥区别?

前置++
后置++

指针常量和常量指针

指针常量: pointer-to-const, a pointer that is pointing to an address that holds a constant
常量指针: const-pointer, a constant pointer that cannot change where it is being pointed to.

const修饰成员函数有什么作用


虚函数相关,子类的虚指针和各个成员是如何分布的,虚函数表里是啥样的(难受。。全忘了)

In object-oriented programming with C++ and similar languages, virtual functions and virtual tables (vtables) play a crucial role in implementing polymorphism. Here's an explanation in English:

Virtual Functions and Polymorphism:
Virtual Function Pointer in Subclasses:
Memory Layout of Subclasses:

The memory layout of a subclass instance includes the following components:

Virtual Function Table (Vtable):
Vtable Structure:
Dynamic Dispatch:

In summary, virtual functions and vtables allow for runtime polymorphism by enabling dynamic dispatch of function calls based on the actual object type. The vptr in subclass instances points to the vtable, which contains function pointers for virtual functions, facilitating the correct execution of overridden functions in derived classes.

Examples

https://pabloariasal.github.io/2017/06/10/understanding-virtual-tables/

image

Note that vtables exist at the class level, meaning there exists a single vtable per class, and is shared by all instances.

image

when a call to a virtual function on an object is performed, the vpointer of the object is used to find the corresponding vtable of the class. Next, the function name is used as index to the vtable to find the correct (most specific) routine to be executed. Done!

Virtual Destructors
#include <iostream>

class Base
{
public:
  ~Base()
  {
    std::cout << "Destroying base" << std::endl;
  }
};

class Derived : public Base
{
public:
  Derived(int number)
  {
    some_resource_ = new int(number);
  }

  ~Derived()
  {
    std::cout << "Destroying derived" << std::endl;
    delete some_resource_;
  }

private:
  int* some_resource_;
};

int main()
{
  Base* p = new Derived(5);
  delete p;
}

// result
// > Destroying base

Making Base’s destructor virtual will result in the expected behavior:

// > Destroying derived
// > Destroying base

问vector和list的区别,空间分布上的区别

Vector (std::vector):
List (std::list):

In summary, the key differences in space distribution between std::vector and std::list are:

The choice between vector and list depends on the specific requirements of the application, such as the frequency of insertions, deletions, and element access operations.


问vector是怎么扩容的

When a std::vector in C++ needs to expand its capacity to accommodate more elements, it follows a process known as reallocation and growth strategy. Here's an explanation in English of how std::vector expands:


问unordered_map的空间复杂度

In summary, the space complexity of std::unordered_map is typically O(n) in the worst case, but it can be more efficient in practice due to its hash table implementation, which aims to distribute elements evenly across buckets to optimize memory usage and access times.


Wrong implementation

class A
{
    public:
        int &x;
};
class A {
public:
    int& x = someInteger; // Initialized at the point of declaration
};

inline是不是一定会被替换?(一脸懵逼)

vector 特点 resize & reserve (忘记了,二面蒙蔽)

explicit

宏定义

Timothyoung97 commented 3 months ago

Round 1

Leetcode: Longest connecting sets of words, last letter must be the same as the first letter of the other word.

Timothyoung97 commented 3 months ago

https://blog.csdn.net/techforward/article/details/135956548

Timothyoung97 commented 2 months ago

Data Structure and Algo

一个有序单链表查询的复杂度

Time Complexity

2个链表如何判断是否相交

https://www.geeksforgeeks.org/write-a-function-to-get-the-intersection-point-of-two-linked-lists/

[Common] Use hash map

or

Find the intersection point using the difference in node counts

#include <iostream>

struct ListNode {
    int val;
    ListNode* next;
    ListNode(int x) : val(x), next(nullptr) {}
};

// Function to get the length of a linked list
int getLength(ListNode* head) {
    int length = 0;
    ListNode* current = head;
    while (current) {
        length++;
        current = current->next;
    }
    return length;
}

// Function to advance a linked list pointer by a given number of steps
void advanceList(ListNode*& head, int steps) {
    while (steps > 0 && head) {
        head = head->next;
        steps--;
    }
}

// Function to check if two linked lists intersect
bool doLinkedListsIntersect(ListNode* headA, ListNode* headB) {
    int lengthA = getLength(headA);
    int lengthB = getLength(headB);

    // Advance the longer list's pointer to make both lists equal in length
    if (lengthA > lengthB) {
        advanceList(headA, lengthA - lengthB);
    } else if (lengthB > lengthA) {
        advanceList(headB, lengthB - lengthA);
    }

    // Compare nodes in both lists for intersection
    while (headA && headB) {
        if (headA == headB) {
            // Nodes match, intersection found
            return true;
        }
        headA = headA->next;
        headB = headB->next;
    }

    // No intersection found
    return false;
}

int main() {
    // Create linked list 1: 1 -> 2 -> 3 -> 4 -> 5
    ListNode* list1 = new ListNode(1);
    list1->next = new ListNode(2);
    list1->next->next = new ListNode(3);
    list1->next->next->next = new ListNode(4);
    list1->next->next->next->next = new ListNode(5);

    // Create linked list 2: 6 -> 7 -> 8
    ListNode* list2 = new ListNode(6);
    list2->next = new ListNode(7);
    list2->next->next = new ListNode(8);

    // Set intersection point: list1 intersects with list2 at node with value 4
    list2->next->next->next = list1->next->next->next;

    if (doLinkedListsIntersect(list1, list2)) {
        std::cout << "Linked lists intersect.\n";
    } else {
        std::cout << "Linked lists do not intersect.\n";
    }

    return 0;
}

如何判断一个链表是否有环,如何确定环的入口。快慢指针嘛,然后让我数学证明为什么是这个结论。没证出来。。。

#include <iostream>

struct ListNode {
    int val;
    ListNode* next;
    ListNode(int x) : val(x), next(nullptr) {}
};

// Function to check if a linked list has a cycle and find the entrance of the cycle
ListNode* detectCycle(ListNode* head) {
    if (!head || !head->next) {
        return nullptr; // No cycle if the list is empty or has only one node
    }

    ListNode* slow = head;
    ListNode* fast = head;
    bool hasCycle = false;

    // Move slow pointer by one step and fast pointer by two steps until they meet or fast reaches the end
    while (fast && fast->next) {
        slow = slow->next;
        fast = fast->next->next;
        if (slow == fast) {
            hasCycle = true; // Cycle detected
            break;
        }
    }

    // If there's no cycle, return nullptr
    if (!hasCycle) {
        return nullptr;
    }

    // Reset slow pointer to head and move both pointers by one step until they meet at the entrance of the cycle
    slow = head;
    while (slow != fast) {
        slow = slow->next;
        fast = fast->next;
    }

    return slow; // Return the node where the cycle starts (entrance of the cycle)
}

int main() {
    ListNode* head = new ListNode(1);
    head->next = new ListNode(2);
    head->next->next = new ListNode(3);
    head->next->next->next = new ListNode(4);
    head->next->next->next->next = head->next; // Create a cycle

    ListNode* cycleEntrance = detectCycle(head);

    if (cycleEntrance) {
        std::cout << "Linked list has a cycle, entrance at value: " << cycleEntrance->val << std::endl;
    } else {
        std::cout << "Linked list does not have a cycle.\n";
    }

    return 0;
}

map和unorderedmap的区别

Underlying Data Structure:

Ordering:

Performance:

Usage Scenarios:


红黑树和哈希表增删改查的时间复杂度

红黑树 (Red-Black Tree):

哈希表 (Hash Table, 哈希映射/哈希表):


红黑树插入一个数怎么调整的

https://youtu.be/qvZGUFHWChY?si=nD16HTRWNQBMyxs6

红黑树在插入一个新节点时,需要进行一系列的调整操作,以维护红黑树的性质。下面是红黑树插入操作的大致步骤和调整过程:

  1. 插入新节点: 首先按照二叉搜索树的规则将新节点插入到红黑树中,即保证左子树节点的值小于当前节点,右子树节点的值大于当前节点。
  2. 将新节点标记为红色: 新插入的节点默认标记为红色,这样可以保持红黑树的平衡性质。
  3. 进行调整: 在插入后,可能会破坏红黑树的性质,需要进行调整操作。主要的调整操作包括旋转和重新着色,以确保红黑树的五条性质得到满足。Might break property (2), (5).

下面是红黑树插入操作的详细调整过程:

image
Case 0: new node = root

Color new node to black

Case 1: new node's uncle = red && new node's father = red
image image
Case 2: new node's uncle = black (triangle)
image image

Rotate in opposite direction

image
Case 3: new node's uncle = black (line)
image

Rotate in opposite direction

image image image image image image image

Rotation is O(1) operations, because we are simply manipulating pointers.

调整过程会根据具体情况进行不同的操作,保证插入后的红黑树依然满足红黑树的五个性质:

(1) 每个节点是红色或黑色。 (2) 根 (root) 节 (leaf) 点是黑色。 (3) 每个叶子节点(NIL节点)都是黑色。 (4) 每个红色节点的两个子节点都是黑色(不能有两个相邻的红色节点)。 (5) 从任意节点到其每个叶子的所有路径都包含相同数量的黑色节点(黑色平衡性)。

这些调整操作保证了红黑树的平衡性和性质,使得红黑树在插入和删除操作后依然保持高效的查找性能。

image

vector容器不断的pushback不断扩容后,再全部popback掉以后,多余的空间如何回收

当使用 std::vector 容器进行不断的 push_back 操作导致容器不断扩容,并且之后全部进行 pop_back 操作以清空容器时,容器的多余空间不会立即回收,而是由容器自行管理,可能会保留一部分多余空间以便之后的 push_back 操作不需要频繁的重新分配内存。这是为了提高性能,避免频繁的内存分配和释放所带来的开销。

具体来说,std::vector 会保留一部分预留空间(capacity),这个预留空间可以容纳额外的元素,以便之后的插入操作不需要重新分配内存。当容器的元素数量减少到一定程度时,并不会立即释放多余的空间,而是保留在容器内部,以备将来的插入操作使用。

如果需要手动释放容器的多余空间,可以使用 shrink_to_fit 方法。这个方法会要求容器将多余的预留空间释放掉,使得容器的大小与容器中元素的数量相匹配。但是需要注意的是,shrink_to_fit 并不是必然立即回收多余空间的操作,具体回收的效果取决于标准库的实现和具体情况。

#include <iostream>
#include <vector>

int main() {
    std::vector<int> vec;

    // 不断进行 push_back 操作
    for (int i = 0; i < 1000; ++i) {
        vec.push_back(i);
    }

    std::cout << "Capacity after push_back: " << vec.capacity() << std::endl;

    // 清空容器
    vec.clear();

    std::cout << "Capacity after clear: " << vec.capacity() << std::endl;

    // 使用 shrink_to_fit 方法释放多余空间
    vec.shrink_to_fit();

    std::cout << "Capacity after shrink_to_fit: " << vec.capacity() << std::endl;

    return 0;
}

在上面的示例中,vec.shrink_to_fit() 调用之后,容器会尝试释放多余的预留空间,使得容器的大小与元素数量相匹配。但是请注意,shrink_to_fit 并不保证一定会回收多余空间,具体效果取决于标准库的实现和内存管理策略。


大根堆建堆的时间复杂度,我说nlogn,他说nlogn已经是排序算法级别的复杂度了,你堆排只建堆就花了nlogn,不是性能比别的算法差?我。。。就说堆高度逐渐增加的,可能应该是log1+log2+...+logn,不知道对不对。

Building a max heap
Heap sort, O(n log n)
image image image image image image image

Hash Collision

Hash collision resolution is the process of handling situations where two or more keys hash to the same index in a hash table. This collision can occur due to the finite range of hash values compared to the potentially infinite set of keys. There are several techniques to resolve hash collisions:

Separate Chaining:
Open Addressing:
Robin Hood Hashing:
Cuckoo Hashing:
Timothyoung97 commented 2 months ago

Leetcode Questions

算法题,2个和坐标轴平行的矩形,如何判断它们是否相交。不用全写出来,写了个思路。我说完他问我是不是在哪见过这个题。。。是不是我答的太快了。然后他给我整了个升级版,2个不平行与坐标轴的矩形怎么判断相交。我。。。不会。


算法题:求a的n次方,其中n是正整数(快速幂)

用O(n)的时间和O(1)的空间,找到给定数组中没出现过的最小正整数。


struct Node {
    int key;
    int val;
    Node *next;
    Node *prev;
    Node(int key, int val) : key(key), val(val), next(nullptr), prev(nullptr) {}
};

class LRUCache {
public:
    int capacity;
    unordered_map<int, Node*> dic;
    Node *head = new Node(-1, -1);
    Node *tail = new Node(-1, -1);
    LRUCache(int capacity) {
        this->capacity = capacity;
        head->next = tail;
        tail->prev = head;
    }

    int get(int key) {
        if (dic.find(key) == dic.end()) {
            return -1;
        }

        Node *node = dic[key];
        remove(node);
        add(node);
        return node->val;
    }

    void put(int key, int value) {
        if (dic.find(key) != dic.end()) {
            Node *oldNode = dic[key];
            remove(oldNode);
        }

        Node *node = new Node(key, value);
        dic[key] = node;
        add(node);

        if (dic.size() > capacity) {
            Node *nodeToDelete = head->next;
            remove(nodeToDelete);
            dic.erase(nodeToDelete->key);
        }
    }

    void add(Node *node) {
        Node *previousEnd = tail->prev;
        previousEnd->next = node;
        node->prev = previousEnd;
        node->next = tail;
        tail->prev = node;
    }

    void remove(Node *node) {
        node->prev->next = node->next;
        node->next->prev = node->prev;
    }

};

/**
 * Your LRUCache object will be instantiated and called as such:
 * LRUCache* obj = new LRUCache(capacity);
 * int param_1 = obj->get(key);
 * obj->put(key,value);
 */
Timothyoung97 commented 2 months ago

OS

image

问虚拟内存是什么,有什么好处

问什么时候诱发缺页中断,问是不是每次访存都要经过操作系统,问知不知道MMU(内存管理单元)

问什么是空间局部性,对编程有什么启发

问为什么32位整型数可以直接做加减法

Timothyoung97 commented 2 months ago

Round 2

Graphics:

C++:

Algo:

Timothyoung97 commented 2 months ago

HR Prep

image image image

What is Hoyoverse/MiHoYo?

What games are under Hoyoverse/MiHoYo?

MiHoYo has developed several notable games, including:

These games showcase MiHoYo's range in genres, from action-packed adventures to puzzle-solving and romance simulations.

Game Development Process

The development pipeline for games typically involves several stages, each with specific tasks and roles. Here's a general overview:

Different roles

Do you understand your role in the line of business?

Game Client Engineer:
Game Engine Engineer:

Strength vs Weakness

Difficult

Timothyoung97 commented 2 months ago