算法_亲密字符串(#859)

83 阅读3分钟

题目

两个字符串,只交换一次其中一个字符串中的两个字母,得到相同的结果就返回true,否则就返回false;

image.png

分析一波

基本分为这几种情况:  

第一种: (两个字符串相等)

  1. 里面没有相同的字母,那么怎么交换都不可能相等的;如:abcd和abcd;
  2. 里面有相同的字母,那么里面的相同字母交换,最终字符串还是不变的,如:abcc和abcc;

第二种:(两个字符串不相等)   

  1. 两个字符串长度不相等,那肯定怎么调换位置都不会相等的;  比如:abcde,abcdef;
  2. 字符串长度相等,  又因为只能交换一次,所以如果两个字符串里面仅仅两处不相等的地方,交换了位置都不相等的话,那么永远不会相等的。比如:abdc和abcd。而abdc和abgt以及abdc和abce就不符合;

实践,上代码分析

/**
 * @param {string} s
 * @param {string} goal
 * @return {boolean}
 */
var buddyStrings = function(s, goal) {
    let result=[],i=0,j;
    const change=()=>{
     for(let i=0;i<s.length;i++){
       if(result[s[i]]) return true;
        result[s[i]]=1;
     }
     return false;
    }
    if(s===goal) return change();
    if(s.length!==goal.length) return false;
    while(s[i]===goal[i]) i++;
    
    for(j=i+1;j<s.length;j++){
        if(s[j]===goal[j]) continue; 
        if(s[i]!==goal[j]||s[j]!==goal[i]) return false;
        break;
        
    }
    if(j===s.length) return false;
    for(j=j+1;j<s.length;j++){
        if(s[j]!==goal[j]) return false;
        
    }
    return true;

};

定义一个数组reasult去存s字符串里面的每位字符的值,从而去判断s字符串里是否有相同的字母;
同时定义i和j后面代码要去用;
写了一个change方法是做字符是否有相同字符的判断的。里面使用一个for循环,判断s里当前位置值的属性在reasult里面是否有值,有的话就直接返回个true,因为s字符串里有相同的字母;
否则就在当前值属性在reasult里面去赋值为1. 这是标记当前字母的,认为已经出现过了;
如果这个循环都完了也没有相同的字母,就直接按返回false.
首先判断第一种情况: 看两个字符是否相等,相等的话就去调用change方法去判断里面是否有重复的字母;
第二种情况,两个字符串不相等;
然后再使用while去找出两个字符串不相等的第一个位置;
再使用一个for循环去找两个交叉值是否相等;
for循环里面,s和goal字符串相同位置的值相等话的就直接退出当前的循环,进入下一次循环; 如果两个交叉值不相等,那么永远不会相等了;就直接返回false;
如果交叉值相等,那么我们需要再往后看看,看后面还有没有不相等的值;
能走出循环,这里又有两种情况:
1种是只有一对不相等:
比如:abcdr和abedr,这种情况也能走到这里,因为走到循环里面,对比j这个位置上的,两个字符串这时候i对应的字符分别是c和e,而j这个位置对应的都是是d这个字符,相等,j++,再次走循环j对应的是r这个字符,两者还是相等,j++;但是j已经大于s.length了所以退出循环;
这时候判断如果j等于s.legth的话,就说明,字符串已经走完了,但里面只有一对不相等,那么就永远不会相等了,所以直接返回false;
第2种:里面有两个交叉值相等,但是字符串还没有走完(因为走到两个交叉值相等然后走到break,就直接退出循环了),所以还要看看后面还有没有不相等的值;
再用一个for循环去走s剩下的长度,看它还有没有与goal剩下字符有不相等的,如果有不相等话的,就返回false。