Remove Extra Consecutive


https://dzone.com/articles/my-favorite-coding-interview
Write a function that takes two parameters, a string and an integer. The function will return another string that is similar to the input string, but with certain characters removed. It's going to remove characters from consecutive runs of the same character, where the length of the run is greater than the input parameter.

Ex: "aaab", 2 => "aab"
Ex: "aabb", 1 => "ab"
Ex: "aabbaa", 1 => "aba"

Note: I'm evaluating your answer on the simplicity of your code. The goal is for it to be readable; someone new should be able to walk into this room afterwards and instantly understand what your function is doing.
def remove_extra_consecutive(input_str, max_consecutive_chars):
    output, prev_char, current_char_seen = '', None, 0
    for current_char in input_str:
        if current_char == prev_char:
            current_char_seen += 1
        else:
            current_char_seen = 0
            prev_char = current_char
        if current_char_seen < max_consecutive_chars:
            output += current_char
    return output
While the candidate is writing code, I focus on the following.

Thought process. How do they get to a solution? Did they talk about their strategy?
It needs to work. If it doesn't, I will keep pushing them until it does.
Are the function and the variables well named?
Is the code as simple as possible, but not more simple?
Is the candidate struggling to remember standard library functions? Help them out.

Other Solutions
The most common variant answer I see is conflating the clauses that count the character and append to the output. Typically this results in a bug where the last character in a run is omitted.
def remove_extra_consecutive(input_str, max_consecutive_chars):
    output, prev_char, current_char_seen = '', None, 1
    for current_char in input_str:
        if current_char == prev_char and current_char_seen < max_consecutive_chars:
            current_char_seen += 1
            output += current_char
        else:
            if current_char != prev_char:
                current_char_seen = 1
                output += current_char
        prev_char = current_char
    return output
Another variant is using indexes instead of a named variable for the previous character. This can often lead to an index out of bounds bug. It's also common to forget to add the last character.
def remove_extra_consecutive(input_str, max_consecutive_chars):
    output, current_char_seen = '', 0
    for i in range(len(input_str) - 1):
        if input_str[i] == input_str[i+1]:
            current_char_seen += 1
        else:
            current_char_seen = 0
        if current_char_seen < max_consecutive_chars:
            output += input_str[i]
    if current_char_seen <= max_consecutive_chars:
        output += input_str[i+1]
    return output
Finally some candidates try to alter the input string itself, or sometimes loop indexes, which can lead of off by one errors.
def remove_extra_consecutive(str, max_consecutive_chars):
    for i in range(len(str)):
        j = i + 1
        while j < len(str):
            if str[i] != str[j]:
                break
            if j - i >= max_consecutive_chars:
                str = str[0:j] + str[j+1:]
            j += 1
    return str
I like this problem because it has one simple and robust solution, and a number of more complicated and brittle solutions. If a candidate gets through it quickly and correctly, I follow up by asking them about which edge cases they would want to create unit tests for. If it's in a dynamic language, I ask about how to make the function operate on any iterable.

Google 2013校招笔试题:用swap排序 - 堆 - 博客频道 - CSDN.NET


Google 2013校招笔试题:用swap排序 - 堆 - 博客频道 - CSDN.NET
题目:长度为n的数组乱序存放着0至n-1. 现在只能进行0与其他书的swap,请设计并实现排序。
http://m.blog.csdn.net/blog/fdcumt/10286611
Read full article from Google 2013校招笔试题:用swap排序 - 堆 - 博客频道 - CSDN.NET

[Algo] Parse XML Tree 解析XML文件 - SegmentFault


[Algo] Parse XML Tree 解析XML文件 - SegmentFault
现在有一个Tokenizer,返回的Token都是XML标签或者内容,比如(open, html)(inner, hello)(close, html)表示<html>hello</html>,每一个括号及其内容是一个Token,请问如何表示这个XML文件。
这题首先要想清楚的是,如何表示XML,因为XML是典型的一父多子,我们用树来表示比较好。然后分析下如何用Tokenizer,Tokenizer有点像Iterator,每当我们用Tokenizer拿到一个Token时,如果这是一个Open的Token,我们需要新建一个节点,这个新节点下面也有可能有新节点。如果是一个Inner的Token,我们也需要新建一个节点,但这个节点下面不会有新的节点。如果是一个Close的Token,我们不需要新节点,而且需要保证上一个Open节点不再接纳新节点了,而对于新节点则要附在上一层的节点后面。这里,我们用栈可以保留上一层的节点信息,帮助我们建树。如果这是一个Open的Token,我们需要新建一个节点加入上一层节点后面,并加入栈中。如果是一个Inner的Token,我们也需要新建一个节点加到上一层节点后面,但不加入栈中。如果是一个Close的Token,则把上一层节点弹出栈。
public class XMLParser {
    
    public static void main(String[] args){
        XMLParser xml = new XMLParser();
        XMLNode root = xml.parse("(open,html)(open,head)(inner,welcome)(close,head)(open,body)(close,body)(close,html)");
        xml.printXMLTree(root, 0);
    }
    
    public XMLNode parse(String str){
        // 以右括号为delimiter
        StringTokenizer tknz = new StringTokenizer(str, ")");
        Stack<XMLNode> stk = new Stack<XMLNode>();
        // 将第一个open节点作为根节点压入栈中
        XMLNode root = convertTokenToTreeNode(tknz.nextToken());
        stk.push(root);
        while(!stk.isEmpty()){
            if(!tknz.hasMoreTokens()){
                break;
            }
            XMLNode curr = convertTokenToTreeNode(tknz.nextToken());
            // 得到上一层节点
            XMLNode father = stk.peek();
            // 根据当前节点的类型做不同处理
            switch(curr.type){
                // 对于Open节点,我们把它加入上一层节点的后面,并加入栈中
                case "open":
                    father.children.add(curr);
                    stk.push(curr);
                    break;
                // Close节点直接把上一层Pop出来就行了,这样就不会有新的节点加到上一层节点后面    
                case "close":
                    stk.pop();
                    break;
                // Inner节点只加到上一层节点后面    
                case "inner":
                    father.children.add(curr);
                    break;
            }
        }
        return root;
    }
    
    private XMLNode convertTokenToTreeNode(String token){
        token = token.substring(1);
        String[] parts = token.split(",");
        return new XMLNode(parts[0], parts[1]);
    }
    
    private void printXMLTree(XMLNode root, int depth){
        for(int i = 0; i < depth; i++){
            System.out.print("-");
        }
        System.out.println(root.type + ":" + root.value);
        for(XMLNode node : root.children){
            printXMLTree(node, depth + 1);
        }
    }
}

class XMLNode {
    String type;
    String value;
    List<XMLNode> children;
    
    XMLNode(String type, String value){
        this.type = type;
        this.value = value;
        this.children = new ArrayList<XMLNode>();
    }
}
Read full article from [Algo] Parse XML Tree 解析XML文件 - SegmentFault

IBM面试题:海盗分金算法及其思想 - 好好学习天天向上 - 博客频道 - CSDN.NET


IBM面试题:海盗分金算法及其思想 - 好好学习天天向上 - 博客频道 - CSDN.NET

妈妈有2000元,要分给她的2个孩子。由哥哥先提出分钱的方式,如果弟弟同意,那么就这么分。但如果弟弟不同意,妈妈会没收1000元,由弟弟提出剩下 1000元的分钱方式,这时如果哥哥同意了,就分掉这剩下的1000元。但如果哥哥也不同意,妈妈会把剩下的1000元也拿走,然后分别只给他们每人100元。


问:如果你是哥哥,你会提出什么样的分钱方式,使你有可能得到最多的钱?(最小单位1元)

--------------------
这个问题类似海盗分钱问题

如果第一次被弟弟否定了,由弟弟分,这时如果哥哥不同意,那么他只能得到100块,也就是说,弟弟给哥哥101就行,这时弟弟能拿到899,再往上推,如 果哥哥第一次分给弟弟的钱小于899,弟弟肯定不干,他自己分他能得到899,所以哥哥给弟弟的钱应该大于899,所以应该给弟弟900,自己拿

1100。


附:海盗分金算法分析思路:

10名海盗抢得了窖藏的100块金子,并打算瓜分这些战利品。这是一些讲民主的海盗(当然是他们自己特有的民主),他们的习惯是按下面的方式进行分配:最厉害的一名海盗提出分配方案,然后所有的海盗(包括提出方案者本人)就此方案进行表决。如果50%或更多的海盗赞同此方案,此方案就获得通过并据此分配战利品。否则提出方案的海盗将被扔到海里,然后下一提名最厉害的海盗又重复上述过程。
  所有的海盗都乐于看到他们的一位同伙被扔进海里,不过,如果让他们选择的话,他们还是宁可得一笔现金。他们当然也不愿意自己被扔到海里。所有的海盗都是有理性的,而且知道其他的海盗也是有理性的。此外,没有两名海盗是同等厉害的――这些海盗按照完全由上到下的等级排好了座次,并且每个人都清楚自己和其他所有人的等级。这些金块不能再分,也不允许几名海盗共有金块,因为任何海盗都不相信他的同伙会遵守关于共享金块的安排。这是一伙每人都只为自己打算的海盗。
  最凶的一名海盗应当提出什么样的分配方案才能使他获得最多的金子呢?
  为方便起见,我们按照这些海盗的怯懦程度来给他们编号。最怯懦的海盗为1号海盗,次怯懦的海盗为2号海盗,如此类推。这样最厉害的海盗就应当得到最大的编号,而方案的提出就将倒过来从上至下地进行。
  分析所有这类策略游戏的奥妙就在于应当从结尾出发倒推回去。游戏结束时,你容易知道何种决策有利而何种决策不利。确定了这一点后,你就可以把它用到倒数第2次决策上,如此类推。如果从游戏的开头出发进行分析,那是走不了多远的。其原因在于,所有的战略决策都是要确定:"如果我这样做,那么下一个人会怎样做?"因此在你以下海盗所做的决定对你来说是重要的,而在你之前的海盗所做的决定并不重要,因为你反正对这些决定也无能为力了。
  记住了这一点,就可以知道我们的出发点应当是游戏进行到只剩两名海盗――即1号和2号――的时候。这时最厉害的海盗是2号,而他的最佳分配方案是一目了然的:100块金子全归他一人所有,1号海盗什么也得不到。由于他自己肯定为这个方案投赞成票,这样就占了总数的50%,因此方案获得通过。
  现在加上3号海盗。1号海盗知道,如果3号的方案被否决,那么最后将只剩2个海盗,而1号将肯定一无所获――此外,3号也明白1号了解这一形势。因此,只要3号的分配方案给1号一点甜头使他不至于空手而归,那么不论3号提出什么样的分配方案,1号都将投赞成票。因此3号需要分出尽可能少的一点金子来贿赂1号海盗,这样就有了下面的分配方案:3号海盗分得99块金子,2号海盗一无所获,1号海盗得1块金子。
  4号海盗的策略也差不多。他需要有50%的支持票,因此同3号一样也需再找一人做同党。他可以给同党的最低贿赂是1块金子,而他可以用这块金子来收买2号海盗。因为如果4号被否决而3号得以通过,则2号将一文不名。因此,4号的分配方案应是:99块金子归自己,3号一块也得不到,2号得1块金子,1号也是一块也得不到。

  5号海盗的策略稍有不同。他需要收买另两名海盗,因此至少得用2块金子来贿赂,才能使自己的方案得到采纳。他的分配方案应该是:98块金子归自己,1块金子给3号,1块金子给1号。
  这一分析过程可以照着上述思路继续进行下去。每个分配方案都是唯一确定的,它可以使提出该方案的海盗获得尽可能多的金子,同时又保证该方案肯定能通过。照这一模式进行下去,10号海盗提出的方案将是96块金子归他所有,其他编号为偶数的海盗各得1块金子,而编号为奇数的海盗则什么也得不到。这就解决了10名海盗的分配难题。

  Omohundro的贡献是他把这一问题扩大到有500名海盗的情形,即500名海盗瓜分100块金子。显然,类似的规律依然成立――至少是在一定范围内成立。事实上,前面所述的规律直到第200号海盗都成立。200号海盗的方案将是:从1到199号的所有奇数号的海盗都将一无所获,而从2到198号的所有偶数号海盗将各得1块金子,剩下的1块金子归200号海盗自己所有。
  乍看起来,这一论证方法到200号之后将不再适用了,因为201号拿不出更多的金子来收买其他海盗。但是即使分不到金子,201号至少还希望自己不会被扔进海里,因此他可以这样分配:给1到199号的所有奇数号海盗每人1块金子,自己一块也不要。
  202号海盗同样别无选择,只能一块金子都不要了――他必须把这100块金子全部用来收买100名海盗,而且这100名海盗还必须是那些按照201号方案将一无所获的人。由于这样的海盗有101名,因此202号的方案将不再是唯一的――贿赂方案有101种。
  203号海盗必须获得102张赞成票,但他显然没有足够的金子去收买101名同伙。因此,无论提出什么样的分配方案,他都注定会被扔到海里去喂鱼。不过,尽管203号命中注定死路一条,但并不是说他在游戏进程中不起任何作用。相反,204号现在知道,203号为了能保住性命,就必须避免由他自己来提出分配方案这么一种局面,所以无论204号海盗提出什么样的方案,203号都一定会投赞成票。这样204号海盗总算侥幸拣到一条命:他可以得到他自己的1票、203号的1票、以及另外100名收买的海盗的赞成票,刚好达到保命所需的50%。获得金子的海盗,必属于根据202号方案肯定将一无所获的那101名海盗之列。
  205号海盗的命运又如何呢?他可没有这样走运了。他不能指望203号和204号支持他的方案,因为如果他们投票反对205号方案,就可以幸灾乐祸地看到205号被扔到海里去喂鱼,而他们自己的性命却仍然能够保全。这样,无论205号海盗提出什么方案都必死无疑。206号海盗也是如此――他肯定可以得到205号的支持,但这不足以救他一命。类似地,207号海盗需要104张赞成票――除了他收买的100张赞成票以及他自己的1张赞成票之外,他还需3张赞成票才能免于一死。他可以获得205号和206号的支持,但还差一张票却是无论如何也弄不到了,因此207号海盗的命运也是下海喂鱼。
  208号又时来运转了。他需要104张赞成票,而205、206、207号都会支持他,加上他自己一票及收买的100票,他得以过关保命。获得他贿赂的必属于那些根据204号方案肯定将一无所获的人(候选人包括2到200号中所有偶数号的海盗、以及201、203、204号)。
  现在可以看出一条新的、此后将一直有效的规律:那些方案能过关的海盗(他们的分配方案全都是把金子用来收买100名同伙而自己一点都得不到)相隔的距离越来越远,而在他们之间的海盗则无论提什么样的方案都会被扔进海里――因此为了保命,他们必会投票支持比他们厉害的海盗提出的任何分配方案。得以避免葬身鱼腹的海盗包括201、202、204、208、216、232、264、328、456号,即其号码等于200加2的某一方幂的海盗。
  现在我们来看看哪些海盗是获得贿赂的幸运儿。分配贿赂的方法是不唯一的,其中一种方法是让201号海盗把贿赂分给1到199号的所有奇数编号的海盗,让202号分给2到200号的所有偶数编号的海盗,然后是让204号贿赂奇数编号的海盗,208号贿赂偶数编号的海盗,如此类推,也就是轮流贿赂奇数编号和偶数编号的海盗。

  结论是:当500名海盗运用最优策略来瓜分金子时,头44名海盗必死无疑,而456号海盗则给从1到199号中所有奇数编号的海盗每人分1块金子,问题就解决了。由于这些海盗所实行的那种民主制度,他们的事情就搞成了最厉害的一批海盗多半都是下海喂鱼,不过有时他们也会觉得自己很幸运――虽然分不到抢来的金子,但总可以免于一死。只有最怯懦的200名海盗有可能分得一份赃物,而他们之中又只有一半的人能真正得到一块金子,的确是怯懦者继承财富。


Read full article from IBM面试题:海盗分金算法及其思想 - 好好学习天天向上 - 博客频道 - CSDN.NET

Mentor Graphics Experience for 1 Year Experienced - GeeksforGeeks


Mentor Graphics Experience for 1 Year Experienced - GeeksforGeeks

Interview 1 (45 mins)
Q1) write a function that returns a different string every time it is called.
Answer
just return the time in the form of a string.
Then the question was changed – what if two different computers were calling the same function at the same time?
Answer
append the computer ID (or IP) to the string.
Then the question was again changed- what if the same computer was calling the same function at the same time
Answer
append the processor ID to the string

Q2) given an integer calculate the number of times the binary representation bits change.
Eg in 43 i,e, 0000101001 we have 5 changes from 0 to 1 or 1 to 0 (the 1st, 3rd, 4th, 5th and 6th bit from the right).
Answer
just start from the rightmost bit and keep moving left and see the number of toggle
O(log n) time.
Then he modified the question- reduce the number of comparison by using extra space.
Answer
store the number of toggles for all numbers between 0 to 255 in an array, where array [i] represents the number of toggle in the interger i. Eg array[43]'s value is 5
now divide the 32 bit number into four 8 bits numbers. Calculate the number of toggles in the each of them (through the hash map) and just check the last and first bit of each of those 8 bits number, if they differ from the next bit then add 1 to the count.

Then lunch break

Interview 2

Q1) given an array of integer, find the longest sequence of consecutive natural number in the array such that all numbers less than every number in the sequence occurred before it in the array.

Eg if the array is
4,7,5,9,11,6,8,14,13,12,1
the answer is 3 – 4,5,6 (though the longest consecutive list is 11-14, 13 occurs after 14)

Answer
start from the left and keep storing them in a hash map, where the key is the number itself and the value is the longest consecutive list ending on it.
To set the value of a number, find the value of the current key -1 . If it is present add one to value and store it in current key's value otherwise set it to 1.

in the above list   key value  4    1  7    1  5    2 (because 4's value is 1)  9    1  11   1  6    3(because 5's value is 2)  8    2  14   1  13   1  12   1  1    1   keep the maximum count. 

Q2) design a data structure to find the number of occurrences of a string.
just use a trie where count represent count
struct trie{
int count;
struct trie* children[26];
};

Q3) some question on suffix tree. I don't remember it.

Q4) Design a system which receives a lot of entries (in millions) in a flip flop (with some stops in between) and do the following function- 1) calculate the value of the flip flop at the kth time
2) kth positive edge.

Then we used hash map for this, but the memory constraint is a problem, so he said that the number of stop were very few, so the answer was to use a BST that has the key as the time where the stop occurred.
(i understand that it is a little hard to understand but the question was pretty easy)

Interview 3
Q1) design a B+ tree and code it.


Read full article from Mentor Graphics Experience for 1 Year Experienced - GeeksforGeeks

Find the maximum subarray XOR in a given array


Find the maximum subarray XOR in a given array - GeeksforGeeks
Given an array of integers. find the maximum XOR subarray value in given array. Expected time complexity O(n).
Examples:
Input: arr[] = {1, 2, 3, 4}
Output: 7
The subarray {3, 4} has maximum XOR value

Input: arr[] = {8, 1, 2, 12, 7, 6}
Output: 15
The subarray {1, 2, 12} has maximum XOR value

An Efficient Solution can solve the above problem in O(n) time under the assumption that integers take fixed number of bits to store. The idea is to use Trie Data Structure. Below is algorithm.
1) Create an empty Trie.  Every node of Trie is going to 
   contain two children, for 0 and 1 value of bit.
2) Initialize pre_xor = 0 and insert into the Trie.
3) Initialize result = minus infinite
4) Traverse the given array and do following for every 
   array element arr[i].
       a) pre_xor  = pre_xor  ^ arr[i]
          pre_xor now contains xor of elements from 
          arr[0] to arr[i].
       b) Query the maximum xor value ending with arr[i] 
          from Trie.
       c) Update result if the value obtained in step 
          4.b is more than current value of result.
How does 4.b work?
We can observe from above algorithm that we build a Trie that contains XOR of all prefixes of given array. To find the maximum XOR subarray ending with arr[i], there may be two cases.
i) The prefix itself has the maximum XOR value ending with arr[i]. For example if i=2 in {8, 2, 1, 12}, then the maximum subarray xor ending with arr[2] is the whole prefix.
ii) We need to remove some prefix (ending at index from 0 to i-1). For example if i=3 in {8, 2, 1, 12}, then the maximum subarray xor ending with arr[3] starts with arr[1] and we need to remove arr[0].
To find the prefix to be removed, we find the entry in Trie that has maximum XOR value with current prefix. If we do XOR of such previous prefix with current prefix, we get the maximum XOR value ending with arr[i].
If there is no prefix to be removed (case i), then we return 0 (that’s why we inserted 0 in Trie).
    // Assumed int size
    static final int INT_SIZE = 32;
       
    // A Trie Node
    static class TrieNode
    {
        int value;  // Only used in leaf nodes
        TrieNode[] arr =  new TrieNode[2];
        public TrieNode() {
            value = 0;
            arr[0] = null;
            arr[1] = null;
        }
    }
    static TrieNode root;
      
    // Inserts pre_xor to trie with given root
    static void insert(int pre_xor)
    {
        TrieNode temp = root;
       
        // Start from the msb, insert all bits of
        // pre_xor into Trie
        for (int i=INT_SIZE-1; i>=0; i--)
        {
            // Find current bit in given prefix
            int val = (pre_xor & (1<<i)) >=1 ? 1 : 0;
       
            // Create a new node if needed
            if (temp.arr[val] == null)
                temp.arr[val] = new TrieNode();
       
            temp = temp.arr[val];
        }
       
        // Store value at leaf node
        temp.value = pre_xor;
    }
       
    // Finds the maximum XOR ending with last number in
    // prefix XOR 'pre_xor' and returns the XOR of this 
    // maximum with pre_xor which is maximum XOR ending 
    // with last element of pre_xor.
    static int query(int pre_xor)
    {
        TrieNode temp = root;
        for (int i=INT_SIZE-1; i>=0; i--)
        {
            // Find current bit in given prefix
            int val = (pre_xor & (1<<i)) >= 1 ? 1 : 0;
       
            // Traverse Trie, first look for a
            // prefix that has opposite bit
            if (temp.arr[1-val] != null)
                temp = temp.arr[1-val];
       
            // If there is no prefix with opposite
            // bit, then look for same bit.
            else if (temp.arr[val] != null)
                temp = temp.arr[val];
        }
        return pre_xor^(temp.value);
    }
       
    // Returns maximum XOR value of a subarray in 
        // arr[0..n-1]
    static int maxSubarrayXOR(int arr[], int n)
    {
        // Create a Trie and insert 0 into it
        root = new TrieNode();
        insert(0);
       
        // Initialize answer and xor of current prefix
        int result = Integer.MIN_VALUE;
        int pre_xor =0;
       
        // Traverse all input array element
        for (int i=0; i<n; i++)
        {
            // update current prefix xor and insert it 
                // into Trie
            pre_xor = pre_xor^arr[i];
            insert(pre_xor);
       
            // Query for current prefix xor in Trie and 
            // update result if required
            result = Math.max(result, query(pre_xor));
  
        }
        return result;
    }
https://www.cnblogs.com/1pha/p/8721373.html
假设答案区间为 [L, R], 则答案为 XOR[L, R], 可以将区间分解为 XOR[L,R] == XOR[0, L - 1] ^ XOR[L, R],
因此
  1. 不断更新所以数字的 前缀异或和, 将每一个前缀异或和 都 保存到 01Trie 中
  2. 在 01Trie 中查询与它 异或值最大 的 前缀异或和
  3. 根据 Step2 的结果, 更新 ans. 重复第一步, 直至无剩余元素.
需要注意的是, 对于样例中的 3 8 2 6 4 的 前缀异或和分别 为 3 11 9 15 11, 最大值为15, 区间为 [0, 4), 因此每个Trie的初始状态应存在 0.
struct BinTrie { BinTrie* next[2]; BinTrie() { next[0] = next[1] = NULL; } }; void insertNum(BinTrie* root, unsigned num) { BinTrie* p = root; for(int i = 31; i >= 0; i--) { int index = (num >> i) & 1; if(!p->next[index]) p->next[index] = new BinTrie(); p = p->next[index]; } } unsigned queryDiff(BinTrie* root, unsigned num) { num = ~num; BinTrie* p = root; unsigned ret = 0; for(int i = 31; i >= 0; i--) { int index = (num >> i) & 1; if(!p->next[index]) index = 1 - index; ret += (index << i); p = p->next[index]; } return ret; } int main() { int nTest; scanf("%d", &nTest); while(nTest--) { int nNum; scanf("%d", &nNum); unsigned pre = 0, ans = 0; BinTrie* root = new BinTrie(); // 保证了 [0, x) 区间的合理性 // 否则对于 15 来说, Trie中最大不同的前缀异或和 queryDiff(root, pre) 并不为 0 insertNum(root, 0); while(nNum--) { unsigned num; scanf("%u", &num); pre = pre ^ num; insertNum(root, pre); ans = max(ans, queryDiff(root, pre) ^ pre); } printf("%u\n", ans); } return 0; }
https://blog.csdn.net/u010232171/article/details/49685523
另一种方法是“后缀数组+Trie字典树+贪心算法”。

后缀数组
定义preXori=A1xorA2xor...xorAipreXori=A1xorA2xor...xorAi,那么数组AA内任意子数组的异或和如下
resi,j=preXorixorpreXorj,i<=j
resi,j=preXorixorpreXorj,i<=j

因此,我们需要找到数组AA内所有的后缀子数组的异或和。然后,利用前面的数据,计算每个以AiAi结束的异或和的最大值。
Trie字典树
为了方便寻找合适的后缀数组异或和,利用Trie字典存储每个后缀数组异或和preXoripreXori。preXoripreXori以二进制(01)的形式存储到Trie中,因此该Trie也称为”01”字典树。从Trie的根往叶子节点的方向对应二进制preXoripreXori的高位到低位。例如preXori=(5)10=(101)2preXori=(5)10=(101)2,左数第一个1是高位,第二个1是低位。

该链接是一道Tire树的联系题:
http://blog.csdn.net/u010232171/article/details/43373697

贪心算法
完成上面两步后,开始计算以AiAi结束子数组的最大异或和。思路是用已知的preXori=A1xorA2...xorAipreXori=A1xorA2...xorAi作为Trie树的查询值。在查询过程中,力求找到与该值异或结果最大的值。遵循优先寻找对应二进制位上不同的节点(异或运算的特点1xor0=11xor0=1)。这样,高位趋近1,结果就是最大的。

https://shanzi.gitbooks.io/algorithm-notes/problem_solutions/max_xor_sub_sequence.html
https://github.com/cherryljr/NowCoder/blob/master/Find%20the%20Maximum%20Subarray%20XOR%20in%20an%20Array.java
 * Approach: Trie 对于 Subarray 问题,我们可以考虑 PreSum, Two Pointer, DP 等方法,
 * 经过分析,我们发现也就只有 PreXOR(EOR) 的方法可以用一用。 总体思路为:求所有以 i 作为结尾的 最大异或 子数组。那么答案必定在这里面。
 * 但是我们发现在本题中无法利用 HashMap 实现加速。(因为我们没办法通过它来求得 最大异或和)
 * 因此我们需要考虑另外的一种数据机构来帮我们实现加速。而这里使用的就是 Trie Tree.
 *
 * 我们在 Trie Tree 中放入了放入了 从0到i 的异或值 EOR. 那么根据 异或运算 的性质: A^B=C => B^C=A 我们可以通过
 * 0...i 的异或和计算出 任意 j...i 的异或值: XOR[j...i] = XOR[0...i] ^ XOR[0...j-1]
 *
 * 那么Trie如何实现快速得到 异或后的最大值 呢?(本题的核心部分) 我们是按照这样的策略(其实是一个贪心的做法): 对于一个 int 类型,总共有 32
 * 位。因此我们 Trie Tree 的高度为 32. 当我们想要查询如何获得最大的异或值时, 我们可以 从高位开始 向低位逐位查找 最佳异或值。遵循着
 * 首先满足高位 的做法依次向下查询。 同时:我们还需要注意符号位,这里比较特殊,因为 0 代表正,1代表负。 所以对于 符号位 我们要取与原来位置上 相同
 * 的数, 而对于其他位我们要去与原来位置上 不同的数(异或1后的数)。 如果 取不到 最佳值的话,我们就只能取现有的值了(总共就两个...)
 * 最后假设我们得到的 最大异或和 为:EOR[x]^EOR[y],那么就说明 最大异或和子数组为:[x+1...y] 这样查找下来我们需要循环 32
 * 次,时间复杂度为 O(1) 而我们需要查找 n 个数,因此总体时间复杂度为 O(n)
 */
  public int maxSubarrayXOR(int[] nums) {
    if (nums == null || nums.length == 0) {
      return 0;
    }

    Trie trie = new Trie();
    // 初始化 trie,将 0 将入到 trie 中,因为 X^0=X
    trie.add(0);
    int eor = 0;
    int max = Integer.MIN_VALUE;
    for (int i = 0; i < nums.length; i++) {
      eor ^= nums[i];
      // 在 Trie 中寻找与 eor 异或起来最大的元素,返回异或之后的结果
      max = Math.max(max, trie.maxXOR(eor));
      // 将 eor 加入到 Trie Tree 中
      trie.add(eor);
    }

    return max;
  }

  class TrieNode {
    // Trie Tree 的节点,因为是 2进制,所以我们只需要 0,1 两个节点即可
    TrieNode[] child;

    TrieNode() {
      child = new TrieNode[2];
    }
  }

  class Trie {
    TrieNode root;

    Trie() {
      root = new TrieNode();
    }

    // 将 nums[i] 加入到 Trie Tree 中
    public void add(int num) {
      TrieNode curr = root;
      for (int i = 31; i >= 0; i--) {
        int path = ((num >> i) & 1); // 获得第 i 位上的值
        if (curr.child[path] == null) {
          curr.child[path] = new TrieNode();
        }
        curr = curr.child[path];
      }
    }

    public int maxXOR(int num) {
      TrieNode curr = root;
      int rst = 0;
      for (int i = 31; i >= 0; i--) {
        // 获得第 i 位上的值
        int path = ((num >> i) & 1);
        // 根据 path,我们需要得到相应的最佳 异或值
        // 注意:如果是 符号位 的话,我们取与path相同的值,否则取与 path 不同的值
        int best = i == 31 ? path : (path ^ 1);
        // 判断 curr.child[best] 节点是否存在,存在的话我们就能取到最佳值
        // 否则只能取另外一个值了
        best = curr.child[best] != null ? best : (best ^ 1);
        // 将 rst 的第 i 位置为 path^best
        rst |= ((path ^ best) << i);
        curr = curr.child[best];
      }
      return rst;
    }

  }
https://www.quora.com/How-do-I-find-a-subarray-with-maximum-xor



Suppose you need to find two numbers in an array with maximum XOR. We store the binary representation of every element of the array in trie. Now, for every element in the array, we traverse the trie to find the maximum XOR we can obtain using the element and the elements stored in the trie. The traversal of trie attempts to make the most significant bit 1. The time complexity of this algorithm would be n*(log2(MAX)), where MAX is the maximum element in the array.
For finding the subarray we follow a similar approach. Let us say the subarray with maximum XOR is F(L,R) where L and R are the left and right index of the subarray. Observe that F(L,R) = F(1,L-1) XOR F(1,R) because XOR of two same numbers is 0. So, XOR of F(1,L-1) and F(1,R) would be XOR of only the elements between L and R.
Now, insert in trie F(1,i) for all 1<=i<=n then, all we need to do is find two elements in this trie whose XOR is maximum, which is the problem we discussed above.



Simple Solution is to use two loops to find XOR of all subarrays and return the maximum.
int maxSubarrayXOR(int arr[], int n)
{
    int ans = INT_MIN;     // Initialize result
    // Pick starting points of subarrays
    for (int i=0; i<n; i++)
    {
        int curr_xor = 0; // to store xor of current subarray
        // Pick ending points of subarrays starting with i
        for (int j=i; j<n; j++)
        {
            curr_xor = curr_xor ^ arr[j];
            ans = max(ans, curr_xor);
        }
    }
    return ans;
}


https://www.geeksforgeeks.org/find-maximum-xor-value-sub-array-size-k/
Given an array of integers, the task is to find maximum XOR value of a subarray of size K.
Examples :
Input  : arr[] = {2, 5, 8 ,1 , 1 ,3} k = 3
Output : 15
Explanation : All subrrays of size k (=3) and
              their XOR values are:
 {2, 5, 8} => XOR value =  15
 {5, 8, 1} => XOR value =  12
 {8, 1, 1} => XOR value =  8
 {1, 1, 3} => XOR value =  3
Maximum of all XOR values = 15
An efficient solution takes O(n) time. The idea is simple, we can find XOR value of current subarray of size k by removing first element of previous subarray and adding last element of current subarray. We can remove an element from current XOR by doing XOR of it again because of property of XOR that a ^ x ^ x = a.

    // Returns maximum XOR value of subarray of size k
    static int maximumXOR(int arr[] , int n , int k)
    {
          
        // Compute XOR value of first subarray of size k
        int current_xor = 0 ;
        for (int i = 0 ; i < k ; i++)
            current_xor = current_xor ^ arr[i];
      
        // Traverse rest of the array
        int max_xor = current_xor;
          
        for (int i = k ; i < n; i++)
        {
              
            // First remove previous subarray's first
            // element
            current_xor = current_xor ^ arr[i-k];
      
            // add new element
            current_xor = current_xor ^ arr[i];
      
            // Update maximum xor value
            max_xor = Math.max(max_xor, current_xor);
        }
      
        return max_xor;
    }

Labels

LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

Popular Posts