判断是否在键盘的同一行 Keyboard Row

本文介绍了一种算法,用于从给定的单词列表中找出仅使用美式键盘单行字母即可拼写的单词。通过三种不同的实现方式展示了如何高效地完成这一任务。

问题:

Given a List of words, return the words that can be typed using letters of alphabet on only one row's of American keyboard like the image below.

American keyboard

Example 1:

Input: ["Hello", "Alaska", "Dad", "Peace"]
Output: ["Alaska", "Dad"]

Note:

  1. You may use one character in the keyboard more than once.
  2. You may assume the input string will only contain letters of alphabet.

解决:

①使用一个数组来存储keyboard组成的字符串。遍历传入的words数组,将字符串转换为字符数组,判断字符数组中是否全部与数组中第一个字符在同一行中(所有字符都在同一行),若在同一行则将其加入返回数组中,否则不加入。耗时3ms。

public class Solution {
    public String[] findWords(String[] words) {
        List<String> list = new ArrayList<String>();
        String[] keyboard = {"QWERTYUIOPqwertyuiop","ASDFGHJKLasdfghjkl","ZXCVBNMzxcvbnm"};//一行键盘所表示的字符,用数组表示
        for(String word : words){
            String realWord = word;
            char[] tmp = word.toCharArray();//将单词的字符串转换为字符数组
            int count = 0;//记录在同一行的字符的数目
            for (char t : tmp) {//查看字符数组,看是否所有字符都在同一行
                 if(keyboard[0].indexOf(tmp[0]) != -1){//若字符数组中第一个字符在第一行,则之后的必须在同一行,否则中断
                    if (keyboard[0].indexOf(t) == -1) {
                        break;
                    }
                 }else if (keyboard[1].indexOf(tmp[0]) != -1) {
                    if (keyboard[1].indexOf(t) == -1) {
                        break;
                    }
                 }else if (keyboard[2].indexOf(tmp[0]) != -1) {
                    if (keyboard[2].indexOf(t) == -1) {
                        break;
                    }
                 }
                 count ++;
            }
            if (count == tmp.length) {//整个单词数组的字符都在同一行
                list.add(realWord);
            } 
        }
        String[] res = new String[list.size()];
        for (int i = 0;i < list.size();i ++) {
            res[i] = list.get(i);
        }
        return res;
    }

class Solution {//2ms
    public String[] findWords(String[] words) {
        String[] keyboard = {"QWERTYUIOPqwertyuiop","ASDFGHJKLasdfghjkl","ZXCVBNMzxcvbnm"};
        List<String> res = new ArrayList<>();
        for (String word : words) {
            char[] tmp = word.toCharArray();
            for (int i = 0;i < keyboard.length ;i ++ ) {
                if (keyboard[i].indexOf(tmp[0]) != -1) {
                    int j = 0;
                    for (;j < tmp.length ;j ++ ) {
                        if (keyboard[i].indexOf(tmp[j]) == -1) {
                            break;
                        }
                    }
                    if(j == tmp.length){
                        res.add(word);
                    }
                }
            }
        }
        return res.toArray(new String[res.size()]);
    }
}

②使用一个标记表明某字符是否在该行,大体思路与上一题一致,耗时3ms.

public class Solution {
    public String[] findWords(String[] words) {
        char[] row1Chars = new char[] {'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P'};
        char[] row2Chars = new char[] {'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L'};
        char[] row3Chars = new char[] {'z', 'x', 'c', 'v', 'b', 'n', 'm', 'Z', 'X', 'C', 'V', 'B', 'N', 'M'};
        boolean[] row1 = new boolean[256];
        boolean[] row2 = new boolean[256];
        boolean[] row3 = new boolean[256];

        for(int i = 0; i < row1Chars.length; ++i) row1[row1Chars[i]] = true;                                                     //用于标记该行中是否包含某字符
        for(int i = 0; i < row2Chars.length; ++i) row2[row2Chars[i]] = true;
        for(int i = 0; i < row3Chars.length; ++i) row3[row3Chars[i]] = true;
        ArrayList<String> res = new ArrayList<String>();
        for(int i = 0; i < words.length; ++i) {
            boolean found = true;//标记是否在同一行中找到全部字符
            String curWord = words[i];//用于存储当前字符串
            for(int j = 0; j < curWord.length() && found; ++j) {
                if(!row1[curWord.charAt(j)]) found = false;//判断字符串中第J个字符是否在该行
            }
            if(!found) {
                found = true;
                for(int j = 0; j < curWord.length() && found; ++j) {
                    if(!row2[curWord.charAt(j)]) found = false;
                }
            }
            if(!found) {
                found = true;
                for(int j = 0; j < curWord.length() && found; ++j) {
                    if(!row3[curWord.charAt(j)]) found = false;
                }
            }
            if(found) res.add(curWord);
        }
        return res.toArray(new String[0]);//如果指定的数组能容纳该 res,则返回包含此 res 元素的数组。否则,将根据指定数组的运行时类型和此 res 的大小分配一个新数组。这里给的参数的数组长度是0,因此就会返回包含此 res 中所有元素的数组,并且返回数组的类型与指定数组的运行时类型相同。toArray(new Object[0]) 和 toArray() 在功能上是相同的。 
    }
}

③使用Map存储keyboard内容,键为每个字符,值是它属于哪一行。耗时5ms。

public class Solution {
    public String[] findWords(String[] words) {
        String[] keyBoard = {"QWERTYUIOPqwertyuiop","ASDFGHJKLasdfghjkl","ZXCVBNMzxcvbnm"};
        Map<Character,Integer> map = new HashMap<>();
        for (int i = 0;i < keyBoard.length ;i ++ ) {
            for (char c : keyBoard[i].toCharArray() ) {//在map中保存所有的字符,值表明所属的行
                map.put(c,i);
            }
        }
        List<String> list = new ArrayList<>();
        for (String word : words) {
            char[] tmp = word.toCharArray();
            int index = map.get(tmp[0]);
            for (char t : tmp) {
                if (map.get(t) != index) {
                    index = -1;//不需要额外的flag
                    break;
                }
            }
            if(index != -1) list.add(word);
        }
        return list.toArray(new String[0]);
    }
}

转载于:https://my.oschina.net/liyurong/blog/916004

# T623351 【MX-X18-T1】「FAOI-R6」520 ## 题目描述 如图是一个键盘: ![小键盘](https://cdn.luogu.com.cn/upload/image_hosting/qxqjjdip.png) 或者用表格的形式来看,如下: | | $/$ | $*$ | $-$ | |:-:|:-:|:-:|:-:| | $7$ | $8$ | $9$ | $+$ | | $4$ | $5$ | $6$ | + | | $1$ | $2$ | $3$ | | | $0$ | 0| $.$ | ^ | 你可以敲击空白键外的其他键。 你可以在如下方式中选一种输入: - 从左往右敲击同一横线上的连续三个键,如 `123`。 - 从右往左敲击同一横线上的连续三个键,如 `321`。 - 从上往下敲击同一竖线上的连续三个键,如 `963`。 - 从下往上敲击同一竖线上的连续三个键,如 `369`。 给你一个由三个字符组成的字符串,保证这些字符是 $0\sim 9$ 的数字或 `+-*/.`,你需要判断是否能输入这个串。 注意:你不能两次敲击同一个键,比如 `00.` 无法输入。 ## 输入格式 仅一行,一个长度为 3 的字符串 $S$,表示你需要判断的字符串。 ## 输出格式 输出一行,一个字符串,如果可以则输出 `Yes`,否则输出 `No`。 ## 输入输出样例 #1 ### 输入 #1 ``` 520 ``` ### 输出 #1 ``` Yes ``` ## 输入输出样例 #2 ### 输入 #2 ``` 456 ``` ### 输出 #2 ``` Yes ``` ## 输入输出样例 #3 ### 输入 #3 ``` 985 ``` ### 输出 #3 ``` No ``` ## 输入输出样例 #4 ### 输入 #4 ``` 211 ``` ### 输出 #4 ``` No ``` ## 输入输出样例 #5 ### 输入 #5 ``` /*- ``` ### 输出 #5 ``` Yes ``` ## 输入输出样例 #6 ### 输入 #6 ``` 56+ ``` ### 输出 #6 ``` Yes ``` ## 输入输出样例 #7 ### 输入 #7 ``` 00. ``` ### 输出 #7 ``` No ``` ## 说明/提示 **【样例解释 #1】** ![520](https://cdn.luogu.com.cn/upload/image_hosting/zq623tum.png) **【样例解释 #2】** ![456](https://cdn.luogu.com.cn/upload/image_hosting/heqbe2ef.png) **【数据范围】** 对于 $40\%$ 的数据,$S$ 不包含 $0$ 与 `+-*/.`。 对于 $60\%$ 的数据,$S$ 不包含 `+-*/.`。 对于所有数据,$S$ 由 $0\sim 9$ 的数字与 `+-*/.` 组成,且长度为 $3$。
最新发布
08-25
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值