📜  门| GATE CS Mock 2018年|套装2 |第45章(1)

📅  最后修改于: 2023-12-03 15:42:13.495000             🧑  作者: Mango

GATE CS Mock 2018年-套装2-第45章

本篇题目主要考察程序员的数据结构和算法能力,要求学生能够掌握以下几个方面:

  • 理解基本的数据结构,并且能够灵活运用
  • 能够使用递归;二分查找和动态规划等算法设计思想
  • 熟练使用指针和链表等数据结构

下面我们来详细解析一下几道考题。

问题1

这道题目要求我们给定一个长度为n的数组,初始时其所有元素均为0,在之后的n次操作中会对这个数组进行修改。

  • 修改操作i将a[L[i]],a[L[i]+1],...,a[R[i]]都加上C[i],其中L[i], R[i], C[i]均为正整数。

最终,我们需要输出该数组的每个元素的值。

这道题目的解题思路主要是使用前缀和算法。对于每一个操作,我们可以先对左、右区间的前缀和分别加上C[i]和-C[i],意思是设置前缀和的增加和减少值,而不必改变数组元素。最后再对整个数组求一遍前缀和即可。

时间复杂度:O(n+m),其中m为操作数。

## Solution 1
def solve(n, m, L, R, C):
    ans = [0] * n
    pre = [0] * (n+1)
    for i in range(m):
        pre[L[i]-1] += C[i]
        pre[R[i]] -= C[i]
    for i in range(1, n+1):
        pre[i] += pre[i-1]
    for i in range(n):
        ans[i] = pre[i]
    return ans
问题2

这道题目要求我们做一个简单的表达式求值。表达式只包含加减乘除和小括号,其中乘除的优先级要大于加减。同时,我们需要保证表达式的合法性。

这道题目的解题思路主要是使用栈和中缀表达式转后缀表达式的思想。首先我们将中缀表达式转换成后缀表达式,然后再使用一个栈来计算后缀表达式的值。

时间复杂度:O(n),其中n为表达式的长度。

## Solution 2
def solve(expression):
    # 定义符号优先级表
    priority = {'+': 1, '-': 1, '*': 2, '/': 2, '(': 0}
    # 初始化栈和后缀表达式字符串
    stack, postfix = [], ''
    # 对表达式每个字符逐一判断
    for char in expression:
        # 如果是数字或变量,则将其加入到后缀表达式字符串中
        if char.isdigit() or char.isalpha():
            postfix += char
        # 如果是左括号,则将其加入到栈中
        elif char == '(':
            stack.append(char)
        # 如果是右括号,则将栈中左括号前的符号全部弹出到后缀表达式字符串中,左右括号均不加入后缀表达式中
        elif char == ')':
            while stack[-1] != '(':
                postfix += stack.pop()
            stack.pop()
        # 如果是符号,则比较其与栈顶元素的优先级
        else:
            while len(stack) > 0 and priority[stack[-1]] >= priority[char]:
                postfix += stack.pop()
            stack.append(char)
    # 将栈中剩余符号全部弹出到后缀表达式字符串中
    while len(stack) > 0:
        postfix += stack.pop()
    # 定义操作符表
    operator = {'+': lambda x, y: x+y, '-': lambda x, y: x-y, '*': lambda x, y: x*y, '/': lambda x, y: x/y}
    # 定义操作数栈
    num_stack = []
    for char in postfix:
        if char.isdigit():
            num_stack.append(int(char))
        elif char.isalpha():
            num_stack.append(ord(char) - ord('a') + 1)
        else:
            op2, op1 = num_stack.pop(), num_stack.pop()
            num_stack.append(operator[char](op1, op2))
    # 返回操作数栈中的结果
    return num_stack[0]
问题3

这道题目要求我们实现一个单向链表,并实现几个操作。

  • insertAtBeginning(int data): 在链表头部插入一个值为data的结点。
  • insertAtEnd(int data): 在链表尾部插入一个值为data的结点。
  • insertAfterNthNode(N:ListNode, data:int): 在链表中第N个节点后面插入一个值为data的结点。
  • deleteNodeWithValue(int data): 删除链表中值为data的结点。

这道题目的解题思路主要是定义一个结点类,然后在结点类中实现插入和删除操作。

时间复杂度:插入操作O(1),删除操作O(n),其中n为链表长度。

## Solution 3
class ListNode:
    def __init__(self, x):
        self.val = x
        self.next = None

class LinkedList:
    def __init__(self):
        self.head = None

    def insertAtBeginning(self, data):
        new_node = ListNode(data)
        new_node.next = self.head
        self.head = new_node

    def insertAtEnd(self, data):
        if not self.head:
            self.insertAtBeginning(data)
            return
        curr = self.head
        while curr.next:
            curr = curr.next
        new_node = ListNode(data)
        curr.next = new_node

    def insertAfterNthNode(self, N, data):
        curr = self.head
        for i in range(N):
            if not curr:
                return
            curr = curr.next
        if curr:
            new_node = ListNode(data)
            new_node.next = curr.next
            curr.next = new_node

    def deleteNodeWithValue(self, data):
        if not self.head:
            return False
        if self.head.val == data:
            self.head = self.head.next
            return True
        curr = self.head
        while curr.next and curr.next.val != data:
            curr = curr.next
        if curr.next:
            curr.next = curr.next.next
            return True
        return False

以上是本次考试的三道题目,希望大家都能够拿到高分。