校招算法笔面试 | 华为机试-MP3光标位置

题目

题目链接

解题思路

这是一个模拟题,需要处理以下几种情况:

  1. 歌曲总数 ≤ 4:不需要翻页,只移动光标

    • Up键:光标在第一首时移到最后,否则向上移动
    • Down键:光标在最后时移到第一首,否则向下移动
  2. 歌曲总数 > 4:需要处理翻页

    • 特殊翻页:
      • 第一页按Up:显示最后一页,光标到最后
      • 最后一页按Down:显示第一页,光标到最前
    • 一般翻页:
      • 光标在当前页第一首按Up:向上翻页
      • 光标在当前页最后一首按Down:向下翻页

代码

#include <iostream>
#include <vector>
using namespace std;

class MP3Player {
private:
    int n;          // 总歌曲数
    int cursor;     // 当前光标位置(1-based)
    int pageStart;  // 当前页面起始歌曲编号(1-based)
    
    void handleSmallList(char cmd) {
        if (cmd == 'U') {
            cursor = (cursor == 1) ? n : cursor - 1;
        } else {
            cursor = (cursor == n) ? 1 : cursor + 1;
        }
    }
    
    void handleLargeList(char cmd) {
        if (cmd == 'U') {
            if (cursor == 1) {
                // 特殊翻页:第一首歌按Up
                cursor = n;
                pageStart = max(1, n - 3);
            } else {
                cursor--;
                if (cursor < pageStart) {
                    pageStart = cursor;
                }
            }
        } else {
            if (cursor == n) {
                // 特殊翻页:最后一首歌按Down
                cursor = 1;
                pageStart = 1;
            } else {
                cursor++;
                if (cursor > pageStart + 3) {
                    pageStart = cursor - 3;
                }
            }
        }
    }
    
public:
    MP3Player(int totalSongs) : n(totalSongs), cursor(1), pageStart(1) {}
    
    void process(char cmd) {
        if (n <= 4) {
            handleSmallList(cmd);
        } else {
            handleLargeList(cmd);
        }
    }
    
    void display() {
        // 显示当前页面
        int end = min(pageStart + 3, n);
        for (int i = pageStart; i <= end; i++) {
            cout << i << " ";
        }
        cout << endl;
        // 显示当前选中歌曲
        cout << cursor << endl;
    }
};

int main() {
    int n;
    string commands;
    cin >> n >> commands;
    
    MP3Player player(n);
    for (char cmd : commands) {
        player.process(cmd);
    }
    player.display();
    
    return 0;
}
import java.util.*;

public class Main {
    static class MP3Player {
        private int n;          // 总歌曲数
        private int cursor;     // 当前光标位置(1-based)
        private int pageStart;  // 当前页面起始歌曲编号(1-based)
        
        public MP3Player(int totalSongs) {
            this.n = totalSongs;
            this.cursor = 1;
            this.pageStart = 1;
        }
        
        private void handleSmallList(char cmd) {
            if (cmd == 'U') {
                cursor = (cursor == 1) ? n : cursor - 1;
            } else {
                cursor = (cursor == n) ? 1 : cursor + 1;
            }
        }
        
        private void handleLargeList(char cmd) {
            if (cmd == 'U') {
                if (cursor == 1) {
                    cursor = n;
                    pageStart = Math.max(1, n - 3);
                } else {
                    cursor--;
                    if (cursor < pageStart) {
                        pageStart = cursor;
                    }
                }
            } else {
                if (cursor == n) {
                    cursor = 1;
                    pageStart = 1;
                } else {
                    cursor++;
                    if (cursor > pageStart + 3) {
                        pageStart = cursor - 3;
                    }
                }
            }
        }
        
        public void process(char cmd) {
            if (n <= 4) {
                handleSmallList(cmd);
            } else {
                handleLargeList(cmd);
            }
        }
        
        public void display() {
            int end = Math.min(pageStart + 3, n);
            for (int i = pageStart; i <= end; i++) {
                System.out.print(i + " ");
            }
            System.out.println();
            System.out.println(cursor);
        }
    }
    
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        String commands = sc.next();
        
        MP3Player player = new MP3Player(n);
        for (char cmd : commands.toCharArray()) {
            player.process(cmd);
        }
        player.display();
    }
}
class MP3Player:
    def __init__(self, total_songs):
        self.n = total_songs        # 总歌曲数
        self.cursor = 1             # 当前光标位置(1-based)
        self.page_start = 1         # 当前页面起始歌曲编号(1-based)
    
    def handle_small_list(self, cmd):
        if cmd == 'U':
            self.cursor = self.n if self.cursor == 1 else self.cursor - 1
        else:
            self.cursor = 1 if self.cursor == self.n else self.cursor + 1
    
    def handle_large_list(self, cmd):
        if cmd == 'U':
            if self.cursor == 1:
                # 特殊翻页:第一首歌按Up
                self.cursor = self.n
                self.page_start = max(1, self.n - 3)
            else:
                self.cursor -= 1
                if self.cursor < self.page_start:
                    self.page_start = self.cursor
        else:
            if self.cursor == self.n:
                # 特殊翻页:最后一首歌按Down
                self.cursor = 1
                self.page_start = 1
            else:
                self.cursor += 1
                if self.cursor > self.page_start + 3:
                    self.page_start = self.cursor - 3
    
    def process(self, cmd):
        if self.n <= 4:
            self.handle_small_list(cmd)
        else:
            self.handle_large_list(cmd)
    
    def display(self):
        # 显示当前页面
        end = min(self.page_start + 3, self.n)
        print(' '.join(map(str, range(self.page_start, end + 1))))
        # 显示当前选中歌曲
        print(self.cursor)

# 处理输入
n = int(input())
commands = input().strip()

player = MP3Player(n)
for cmd in commands:
    player.process(cmd)
player.display()

算法及复杂度

  • 算法:模拟
  • 时间复杂度: O ( m ) \mathcal{O}(m) O(m),其中 m m m 是命令的长度
  • 空间复杂度: O ( 1 ) \mathcal{O}(1) O(1),只需要常数额外空间

这个解法通过模拟MP3播放器的行为,维护当前光标位置和页面起始位置,根据不同情况处理上下键的操作。代码结构清晰,分别处理了歌曲数量小于等于4和大于4的情况。

题目链接

解题思路

这道题要求在DNA序列中找出GC-Ratio最高的子串,需要注意以下几点:

  1. GC-Ratio = (G和C的个数) / 子串长度
  2. 子串长度固定为输入的N
  3. 如果有多个子串的GC-Ratio相同,输出第一个

解题步骤:

  1. 使用滑动窗口遍历所有长度为N的子串
  2. 对每个子串计算GC-Ratio
  3. 记录最大GC-Ratio及其对应的子串
  4. 如果遇到相同的GC-Ratio,保持第一个找到的子串不变

代码

#include <iostream>
#include <string>
using namespace std;

string findMaxGCRatio(string dna, int n) {
    if (dna.length() < n) return "";
    
    // 计算第一个窗口的GC数量
    int maxGC = 0;
    int currentGC = 0;
    for (int i = 0; i < n; i++) {
        if (dna[i] == 'G' || dna[i] == 'C') {
            currentGC++;
        }
    }
    maxGC = currentGC;
    int maxStart = 0;
    
    // 滑动窗口
    for (int i = 1; i <= dna.length() - n; i++) {
        // 移除窗口左边的字符的贡献
        if (dna[i-1] == 'G' || dna[i-1] == 'C') {
            currentGC--;
        }
        // 添加窗口右边新字符的贡献
        if (dna[i+n-1] == 'G' || dna[i+n-1] == 'C') {
            currentGC++;
        }
        // 更新最大值
        if (currentGC > maxGC) {
            maxGC = currentGC;
            maxStart = i;
        }
    }
    
    return dna.substr(maxStart, n);
}

int main() {
    string dna;
    int n;
    while (cin >> dna >> n) {
        cout << findMaxGCRatio(dna, n) << endl;
    }
    return 0;
}
import java.util.Scanner;

public class Main {
    public static String findMaxGCRatio(String dna, int n) {
        if (dna.length() < n) return "";
        
        // 计算第一个窗口的GC数量
        int maxGC = 0;
        int currentGC = 0;
        for (int i = 0; i < n; i++) {
            if (dna.charAt(i) == 'G' || dna.charAt(i) == 'C') {
                currentGC++;
            }
        }
        maxGC = currentGC;
        int maxStart = 0;
        
        // 滑动窗口
        for (int i = 1; i <= dna.length() - n; i++) {
            if (dna.charAt(i-1) == 'G' || dna.charAt(i-1) == 'C') {
                currentGC--;
            }
            if (dna.charAt(i+n-1) == 'G' || dna.charAt(i+n-1) == 'C') {
                currentGC++;
            }
            if (currentGC > maxGC) {
                maxGC = currentGC;
                maxStart = i;
            }
        }
        
        return dna.substring(maxStart, maxStart + n);
    }
    
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while (sc.hasNext()) {
            String dna = sc.next();
            int n = sc.nextInt();
            System.out.println(findMaxGCRatio(dna, n));
        }
    }
}
def find_max_gc_ratio(dna, n):
    if len(dna) < n:
        return ""
    
    # 计算第一个窗口的GC数量
    current_gc = sum(1 for c in dna[:n] if c in 'GC')
    max_gc = current_gc
    max_start = 0
    
    # 滑动窗口
    for i in range(1, len(dna) - n + 1):
        # 更新当前窗口的GC数量
        if dna[i-1] in 'GC':
            current_gc -= 1
        if dna[i+n-1] in 'GC':
            current_gc += 1
            
        # 更新最大值
        if current_gc > max_gc:
            max_gc = current_gc
            max_start = i
            
    return dna[max_start:max_start+n]

while True:
    try:
        dna = input().strip()
        n = int(input())
        print(find_max_gc_ratio(dna, n))
    except:
        break

算法及复杂度

  • 算法:滑动窗口
  • 时间复杂度: O ( N ) \mathcal{O}(N) O(N),其中 N N N 是DNA序列的长度
  • 空间复杂度: O ( 1 ) \mathcal{O}(1) O(1),只需要常数额外空间
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值